集合的框架:
前面我们保存多个数据使用的是数组。数组有不足的地方
数组的特点如下所示:
(1)长度开始时必须指定,而且一旦指定,不能更改
示例如下:
我们创建了一个数组:int [] n=new int[3]。
声明数组的方式有以下两种:1。数据类型 [ ]数组名=null; int [ ]n=null
2.数据类型[ ]数组名;
数组名=new 数据类型[长度 ];(int [] n;n=new int [10])
数组的静态初始化有两种方式,具体格式如下:
类型 [ ]数组名 =new 类型[ ]{元素,....}
类型 [ ]数组名={元素,元素.......}
当我们对这个数组进行扩容的时候,我们需要创建一个新的数组,然后再把原数组拷贝过去很麻烦。
(2)保存的必须为同一类型的元素
(3)使用数组进行增加或者删除元素的示意代码--比较麻烦
示例如下所示:我们有一个Person数组,
Person[ ] pers=new Person[ 1]; //大小是1,对于这个数组增加一个新的person对象。
我们的做法如下:
(1)创建一个新的数组:
Person [ ] pers2=new Person[pers.length+1]; //新创建一个数组
(2)
for(){} /拷贝pers数组的元素到pers2
(3)
pers2[pers2.length-1]=new Person();//添加新的对象
我们的示例代码如下所示:
package com.rgf.servlet.user;
public class J {
public static void main(String[] args) {
int[ ] pers={1,2,3,4,5}; //大小是1,对于这个数组增加一个新的person对象。
int jihe=100;
int [ ] pers2=new int[pers.length+1];
for(int i=0;i<pers.length;i++){
pers2[i]=pers[i];
}
pers2[pers2.length-1]=jihe;//添加新的对象
for (int j = 0;j<pers2.length;j++){
System.out.println(pers2[j]);
}
}
}
运行界面如下所示:
集合(多种数据放在一起):
(1)可以动态保存任意多个对象,使用比较方便
(2)提供了一系列方便的操作对象的方法:add、remove、set、get等
(3)使用集合添加、删除新元素的示意代码-简洁了
集合的框架体系:
java的集合类很多,主要分为两大类,如图:
Collection.java
package com.rgf.jihe;
/**
* 一、集合框架的概述
* 1.集合、数组都是对多个数据进行存储操作的结构,简称java容器。
* 说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中)
* 2.1数组在存储多个数据方面的特点:
* >一旦初始化以后,其长度就确定了。
* >比如:数组一旦定义好,其元素的类型1也就确定了。我们也就只能操作指定类型的数据了。
* Stirng[] arr,int [] arr1;Object [] arr2;
* 2.2数组在存储多个数据方面的缺点:
* >一旦初始化以后,其长度就不可修改。
* >数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
* >获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
* >数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。
*二、集合框架
* 1.Collection接口(单列集合,用来存储一个一个的对象)
* set(无序不可重复):hashset、treeset、Linkedhashset
* list(有序可重复,动态数组):linkedlist、Arraylist、Vector
* 2.Map接口(双列集合,用来存储一对(key - value)一对的数据)
* hashMap、LinkedHashMap、Hashtable、properties
* treemap
*/
public class ConnectionTest {
}
collection集合为单列集合。(单列集合即为在这个集合里面放的单个的对象)
其中,Linkedlist为链表的list,ArrayList为数组的list。
Map集合为双列集合(双列集合放的是键值对形式的)
集合主要是两组:双列集合(Map集合)和单列集合(Collection集合)。
Collection接口有两个重要的子接口:Set(元素无序、不可重复的集合)和List(元素有序、可重复的集合),他们的实现子类都是单列集合。(里面放的单个单个的元素)
Map接口的实现子类:HashMap和TreeMap,HashTable。他们的实现子类为双列集合(里面放的为键值对,为key-value形式的值)
我们更加形象的查看双列集合和单列集合:
//添加单列集合
ArrayList arrayList = new ArrayList();
arrayList.add("jdbc");
arrayList.add("javaweb");
HashMap hashMap = new HashMap();
//添加双列集合
hashMap.put("number1","北京");
hashMap.put("number2","上海");
Collection接口:
Collection接口实现类的特点:
public interface Collection <E> extends Iterable<E>
(1)Collection实现子类可以存放多个元素,每个元素可以是Object
(2)有些Collection的实现类,可以存放重复的元素(List),有些不可以(Set)
(3)有些Collection的实现类,有些是有序的(List),有些不是有序(Set)
(4)Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的。
Collection接口的常用方法:
向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals().
由于Collection接口本身不能被实例化的,我们以实现子类ArrayList来进行示例:
package com.rgf.collection;
import java.util.ArrayList;
import java.util.List;
public class CollectionMethod {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list = new ArrayList();
//add:add(Object e):将元素e添加到集合coll中
list.add("jdbc");
list.add(10);//所添加的数已经不是基本数据类型,而是对象,本质是这么装的:list.add(new Integer(10)) 自动装箱
list.add(true);
System.out.println("list="+list);
//remove:删除指定元素
//remove(Object o),删除的是一个对象,返回的就是一个boolean值,即为是否删除成功
//remove(int index),删除的是一个索引值,返回的是被删除的对象。
list.remove("jdbc");
System.out.println("list="+list);
list.remove(0);//删除第一个元素
System.out.println("list="+list);
//contains:查找元素是否存在(contains(Object obj):判断当前集合中是否包含obj,判断的是内容,而不是地址。String重写过了equals方法,是比较内容,如果没有重写equals方法,在调用equals的时候是调用Object里面的,里面为==。
//我们在判断时会调用obj对象所在类的equals()。
System.out.println(list.contains(true));//返回true
System.out.println( list.contains("rgf"));//返回false
//size:获取添加的元素的个数
System.out.println(list.size());//1
//isEmpty:判断当前集合是否为空
System.out.println(list.isEmpty());
//clear:清空
list.clear();
System.out.println("list"+list);
//addAll:添加多个元素,addAll(Connection c),实现了Connection接口的类的一个对象都可以传进去
List list2 = new ArrayList();
list2.add("三国演义");
list2.add("红楼梦");
System.out.println("list2="+list2);
list.addAll(list2);
System.out.println("list="+list);
//containsAll:查找多个元素是否都存在
System.out.println(list.containsAll(list2)); //true
//removeAll:删除多个元素.以下代码为把list里面中的所有list2中的元素全部删掉,即把他们的交集删掉。
list.add("水浒传");
list.removeAll(list2);
System.out.println("list="+list);
}
}
我们运行之后,如下所示:
方法示例二:
package com.rgf.jihe;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* 一、集合框架的概述
* 1.集合、数组都是对多个数据进行存储操作的结构,简称java容器。
* 说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中)
* 2.1数组在存储多个数据方面的特点:
* >一旦初始化以后,其长度就确定了。
* >比如:数组一旦定义好,其元素的类型1也就确定了。我们也就只能操作指定类型的数据了。
* Stirng[] arr,int [] arr1;Object [] arr2;
* 2.2数组在存储多个数据方面的缺点:
* >一旦初始化以后,其长度就不可修改。
* >数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
* >获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
* >数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。
*二、集合框架
* 1.Collection接口(单列集合,用来存储一个一个的对象)
* set(无序不可重复):hashset、treeset、Linkedhashset
* list(有序可重复,动态数组):linkedlist、Arraylist、Vector
* 2.Map接口(双列集合,用来存储一对(key - value)一对的数据)
* hashMap、LinkedHashMap、Hashtable、properties
* treemap
*/
public class ConnectionTest {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(123);
list.add(456);
list.add(new Person("Jerry",20));
ArrayList list1 = new ArrayList();
list1.add(123);
list1.add(456);
list1.add(new Person("Jerry",20));
//retainAll(Collection coll1):获取当前集合和list1集合的交集,并返回给当前集合
list.retainAll(list1);
System.out.println(list); //[123,
//equals(Object obj):要想返回true,需要当前集合和形参集合的元素都相同。
// 如果顺序不一致,也不一样,实现类ArrayList是有序的
System.out.println(list.equals(list1));
//hashCode():返回当前对象的哈希值
System.out.println(list.hashCode());
//集合 --->数组:toArray()
Object[] objects = list.toArray();
for (int i=0;i< objects.length;i++){
System.out.println(objects[i]);
}
//数组--->集合:调用Arrays类的静态方法aList()
List<String> LIST = Arrays.asList(new String[]{"AA", "BB", "CC"});
System.out.println(LIST);
List<int[]> ints = Arrays.asList(new int[]{123, 456});
System.out.println(ints);
System.out.println(ints.size()); //1
List ints1 = Arrays.asList(new Integer(789),new Integer(441));
System.out.println(ints1);
System.out.println(ints1.size());
//iterator():返回Iterator接口的实例,用于遍历集合元素。
}
}
class Person{
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (age != person.age) return false;
return name != null ? name.equals(person.name) : person.name == null;
}
}
运行之后如下所示:
Collection接口遍历元素方式1----使用Iterator(迭代器)
我们可知:Collection的父接口为Iterable。
我们查看Iterator的源码如下所示:
我们发现Iterable里面有个很重要的方法,即为Iterator方法。
可以通过Iterator方法返回一个Iterator对象。Iterator对象就是我们所说的迭代器对象。
我们可以使用Iterator对象进行所有元素的一个遍历。
只要是实现了Collection接口的子类,都可以去获取到一个Iterator(迭代器),然后用这个迭代器来遍历这个集合里面的所有对象。
(1)Iterator对象称为迭代器,主要用于遍历Collection集合中的元素
(2)所有实现了Collection接口的集合类都有一个Iterator()方法,用以返回一个实现了Iterator接口的对象,既可以返回一个迭代器。
(3)Iterator的结构:
迭代器的执行原理:
我们有一个竖表:
123 |
AA |
new Date() |
1 |
2 |
这个表相当于数组一样,可以把数据都存放进里面去,当我们通过Iterator方法,得到一个迭代器后,我们每次调用这个迭代器的next方法,就会往下移动 一格,每调用一次,往下移动一次,并且把这个数据取出来,直到把最后一个数据取出来之后,再往下移动之后,取不到东西从而退出。
Iterator iterator =coll.iterator();//得到一个集合的迭代器
//hasNext():判断是否还有下一个元素,没有会返回false(Iterator对象的一个方法)
while(Iterator.hasNext()){ //返回false后,这个循环会结束
//next():1指针下移2.将下移以后集合位置上的元素返回
System.out.println(iterator.next());
}
我们进行查看源码:
Iterator接口里面有个hasNext方法,hasNext方法会如果iteration有更多的元素,会返回true。没有更多的元素则会返回false。
其中的next()方法有两个作用://next():1指针下移2.将下移以后集合位置上的元素返回
Iterator接口的方法:
注意:在调用Iterator.next()方法之前必须要调用Iterator.hasNext().
进行检测,若不调用,且下一条记录无效,直接调用Iterator.next()会抛出NoSuchElementException异常。
我们发现迭代器里面有一个remove.我们进行实现如下所示:
package com.rgf.jihe;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 集合元素的遍历操作,使用迭代器Iterator接口
* 1.内部的方法:hasNext()和next()
* 2.集合对象每次调用iterator()方法都得到一个全新的迭代器对象
* 默认游标都在集合的第一个元素之前
* 3.内部定义了remove(),可以在遍历的时候,删除集合中的元素,此方法不同于集合直接调用remove()
*
*/
public class Iterator2 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("123");
list.add("456");
list.add(new String("沃尔"));
//Iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法。
//如果还未调用next()或在上一次调用next方法之后已经调用了remove方法,再调用remove都会报IllegalStateException
Iterator iterator = list.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
if("沃尔".equals(next)){
iterator.remove();
}
}
Iterator iterator1 = list.iterator();
while (iterator1.hasNext()){
System.out.println( iterator1.next());
}
}
}
运行之后如下所示:
(4)Iterator仅用于遍历集合,并不是容器,Iterator本身并不存放对象。
Iterator接口的实现:
package com.rgf.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class CollectionIterator {
public static void main(String[] args) {
List col = new ArrayList();
col.add(new Book("三国演义","罗贯中",52.2));
col.add(new Book("西游记","吴承恩",22.5));
col.add(new Book("红楼梦","曹雪芹",32.8));
System.out.println("col="+col);
//我们进行输出的时候发现是连着输出,但是现在我们希望一个一个进行取出。如下所示:
//先得到col对应的迭代器
Iterator iterator = col.iterator();
//此时返回iterator对象的时候,此时的指针是指在第一个对象的上面。当调用hasNext的时候,判定为true的时候,执行next,此时返回第一个数的同时,指针进行下移。之后再次调用next.
//使用while循环遍历,我们可以使用快捷键进行快速循环:itit,
// 显示所有的快捷键的快捷键:ctrl+j,我们可以查看当前的快捷模板。
while(iterator.hasNext()){ //hasNext:判断集合中是否还有下一个元素
//返回下一个元素,类型是object。
Object object = iterator.next();//取出集合中的对象
//编译类型为object,但是我们的运行类型是取决于我们真正存放的类型。
System.out.println("object="+object);
}
//当迭代器退出while循环后,这是iterator指向了最后的元素。
// iterator.next(); //NoSuchElementException
//如果希望再次遍历,需要重置我们的迭代器。
iterator=col.iterator();
System.out.println("===第二次遍历===");
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println("next="+next);
}
}
}
class Book{
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
运行界面如下所示:
错误使用迭代器的两种方式如下所示:
package com.rgf.jihe;
import java.util.ArrayList;
import java.util.Iterator;
public class Iterator1 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(123);
list.add(456);
//错误方式一:会报错,同时会间隔输出
Iterator iterator = list.iterator();
while (iterator.next()!=null){
System.out.println(iterator.next());
}
//错误方式二:每当调用list.iterator方法,都会返回一个迭代器对象,这个迭代器的对象是新的,新的就会在数据的开头。就会一直在第一个位置
while (list.iterator().hasNext()){
System.out.println(list.iterator().next());
}
}
}
Collection接口遍历元素方式2----增强for循环
增强for循环,可以代替iterator迭代器,特点:增强for循环就是简化版的iterator,本质一样。只能用于遍历集合或数组。
基本语法:
for(元素类型 元素名:集合名或数组名){
访问元素
}
我们的代码示例如下所示:
package com.rgf.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class CollectionIterator {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List col = new ArrayList();
col.add(new Book("三国演义", "罗贯中", 52.2));
col.add(new Book("西游记", "吴承恩", 22.5));
col.add(new Book("红楼梦", "曹雪芹", 32.8));
//使用增强for循环
//for(元素类型 元素名称: 集合名或元素名)
for(Object book:col){
System.out.println("book="+book);
}
//1.增强for可以直接在数组上使用,也可以在Collection集合使用。
//2.增强for,它的底层仍然是迭代器
//3.可以理解成增强for循环就是简化版本的迭代器遍历
//4.快捷键方式:I
int [] arr={1,8,10,90};
for(int i:arr){
System.out.println("i="+i);
}
}
}
class Book{
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
运行之后如下所示:
增强for循环的底层仍然是迭代器,我们可以通过断点的方式进行查看:
我们点击Debug进行查看:
我们发现进入如下界面。
我们发现进入的页面也是调用了Iterator,调用了hasNext的方法和next的方法。
增强for循环内部仍然使用的是迭代器Iterator。
我们进行如下练习:
package com.rgf.jihe;
public class IteratorE {
public static void main(String[] args) {
String[] arr=new String[]{"MM", "MM", "MM"};
//方式一:普通for赋值,这种方式可以将值进行修改
for (int i=0;i<arr.length;i++){
arr[i]="GG";
}
for (String i:arr){
System.out.println(i);
}
String[] arr1=new String[]{"MM", "MM", "MM"};
//方式二:增强for循环,此时我们输出仍然为MM,因为在增强for循环中,我们相当于把arr里面的数据先取出来,然后赋值给s,我们修改的是s,
//而不是arr。所以仍然为MM.
for(String s:arr1){
s="GG";
}
for (String i:arr1){
System.out.println(i);
}
}
}
我们运行之后如下所示:
小测试:
编写程序CollectionExercise.java
1.创建3个Dog(name,age)对象,放入到ArrayList中,赋给List引用
2.用迭代器和增强for循环两种方式来遍历
3.重写Dog的toString方法,输出name和age。
我们首先创建:
package com.rgf.collection;
public class CollectionExercise {
public static void main(String[] args) {
}
}
之后编写Dog类。
package com.rgf.collection;
public class CollectionExercise {
public static void main(String[] args) {
}
}
class Dog{
private String name;
private int age;
}
设置他们的构造器和getter和setter方法和toString方法:
package com.rgf.collection;
public class CollectionExercise {
public static void main(String[] args) {
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
之后我们进行创建集合,进行遍历输出:
package com.rgf.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class CollectionExercise {
public static void main(String[] args) {
List list = new ArrayList();
list.add(new Dog("小黑",10));
list.add(new Dog("大黄",15));
list.add(new Dog("jack",5));
//先使用增强for循环。
for (Object dog :list) {
System.out.println("dog="+dog);
}
//使用iterator迭代器
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object dog = iterator.next();
System.out.println("dog="+dog);
}
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
运行之后如下所示: