今日任务
1、集合框架继承体系(理解)
2、Collection接口介绍(掌握常用Collection方法)
3、迭代器(掌握)
4、集合的细节
5、集合使用的步骤
1、集合框架的继承体系
集合是用来存储数据的一类容器,但是在使用集合存储数据时,也会有不同的存储需求。例:存储的数据不能有重复的、存储的数据可以自动排序、存储的数据无序。针对不同的存储需求,java设计了存储不同需求的集合对象。这些针对不同需求的集合对象,虽然存储方法式不同,但是都具有共性的功能:比如:增、删、改、查(CRUD create read update delete)等操作。所以我们把共性的操作向上抽取,最终形成了一个集合框架的继承体系结构。
既然有上述的共性的规律,于是Java就把这些最基本的规律抽取到了一个接口中。其中一个顶级接口就是:Collection接口。
在集合框架体系中用接口来定义所有集合操作的共性规则。
集合体系框架从JDK1.2才开始存在。早期有集合,但是它们没有形成一个体系。
集合框架的继承体系如下图所示:
说明:
1)Collection是这个体系的顶级接口;
2)Collection中定义了所有集合子类的共性操作;
3)我们先从Collection接口开始学习,将Collection中的函数学完之后,实现类都可以直接使用,最后我们在去学习子类特有的函数就可以了;
4)通过查阅API得知Collection、List、Set接口下面不是只有如上图所示的子类或者子接口,但是我们在开发中主要使用这些集合;
2、集合Collection接口
2.1、Collection接口介绍
Collection接口:它是集合的最顶层接口,它中规定了所有集合中的最基本的操作规律。而Java中提供的所有集合容器都保存在java.util包下。
Collection接口是集合的顶层接口,它下面有子接口或者间接的实现类,而具体的实现类中有些可以保存重复元素,有些不能保存重复元素,有些可以保证数据有序,一些则无序。
说明:在学习集合框架的时候,遇到的所有E类型,全部理解成Object类型。
2.2、Collection中的方法介绍
2.2.1、添加方法
说明:把指定的引用类型数据,添加到集合中。添加成功则返回true。
我们知道Collection是接口,它不能new对象。而Collection中定义的是所有集合共性的操作规律。那么我们就可以随便找个Collection的实现类,例如ArrayList类。这样就可以使用多态的方式来操作集合。
代码举例:Collection coll=new ArrayList();//这里发生多态
步骤和分析:
1)使用new关键字创建集合类ArrayList的对象,对象的类型是接口Collection;
2)使用集合对象coll调用add()函数给集合中添加不同的数据;
package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;
import cn.xuexi.sh.demo.Student;
/*
* Collection接口中add方法的演示
*/
public class CollectionAddDemo {
public static void main(String[] args) {
/*
*由于Collection是接口,所以不能创建Collection接口的对象,
*但是我们可以使用new关键字创建Collection接口下面的任意一个类的对象,然后对象类型变为Collection
*/
Collection coll=new ArrayList();//这里发生多态了
//使用coll对象调用add函数向集合中添加引用类型数据
coll.add("aaaa");
//创建学生对象
Student s =new Student("张三",19);
//将自定义类的对象添加到集合中
coll.add(s);
/*
*在集合中是否可以存储基本数据类型?
*正常情况是不可以的,但是从jdk5之后,有了自动装箱和拆箱的功能
*如果使用集合添加基本数据类型,实则jvm是把基本数据类型包装成了对应的包装类对象并存储到集合中了
*/
//Integer valueOf = Integer.valueOf(123);
coll.add(123);//这里相当于coll.add(Integer.valueOf(123));
//Boolean valueOf =Boolean.valueOf(true);
coll.add(**true**);//这里相当于coll.add(Boolean.valueOf(true));
//输出集合中的数据
System.*out*.println(coll);
}
}
说明:
1)add函数可以把一个对象保存在集合中,但是这个函数有返回值boolean,返回的结果是告诉我们是否给集合中添加成功。添加成功则返回true。
2)能否给集合中保存基本类型数据?
严格意义上讲是不可以的,因为集合中只能保存引用类型数据,而基本类型数据不属于引用类型数据,即不属于对象,但是在jdk5之后,基本数据类型有自动装箱和拆箱的机制,因此我们也可以直接把基本类型的数据保存到集合中。
可是集合中存储的根本不是基本类型的数据,而是基本类型数据对应的包装类型的对象。
如:coll.add(100);//此代码存在装箱coll.add(Integer.valueOf(100));
2.2.2、删除方法
步骤:
1)创建集合对象coll;
2)使用集合对象coll调用add()函数向集合中添加数据;
3)输出集合中的数据;
4)使用集合对象coll调用remove()函数删除指定的数据,并使用布尔类型的数据接收删除返回值boo;
5)输出返回值boo和删除后的数据coll;
根据指定的元素,删除集合中对应的元素。删除成功则返回true,否则返回false。
package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;
/*
* Collection接口中的删除方法remove演示
*/
public class Collection RemoveDemo {
public static void main(String[] args) {
//创建集合类对象
Collection coll=**new** ArrayList();
//使用集合对象coll给集合中添加数据
coll.add("abc");
coll.add("aaa");
coll.add("ddd");
coll.add("aaa");
coll.add("yyy");
//输出集合中的数据
System.*out*.println(coll);
//使用集合对象coll调用remove删除函数
boolean boo = coll.remove("aaa");
// boolean boo1 = coll.remove("aaa");
// boolean boo = coll.remove("xxx");//由于要删除的元素不在集合中,所以返回结果是false
System.out.println(boo);
// System.out.println(boo1);
System.out.println(coll);
}
}
清空集合中所有的存储的元素。
步骤:
1)使用集合对象coll调用clear()函数清空集合中的所有元素;
2)输出清空后的集合;
说明:
使用clear()函数清空集合中的元素后,集合容器依然存在,所以还可以继续向集合中添加元素。
问题:
把集合设为null和使用集合对象中的clear()方法有什么区别?
集合=null 表示这个集合对象没有任何引用了。如:coll=null,那么堆中对象的空间就没有任何指向他了,而栈中的coll引用变量空间是一个空指向,所以这里会报空指针异常。
集合.clear() 表示集合中存储的元素全部清空,但是集合对象还存在。
2.2.3、判断方法
boolean contains(Object obj)函数表示判断集合中是否存在指定的元素。
如果有指定的元素,则返回true,没有则返回false。
boolean isEmpty()判断集合是否为空。集合中没有存储任何元素表示为空。
注意:
1)这个函数不是集合引用是否为null,而是判断集合中是否有元素;
2)如果集合中有元素返回false,集合中不包含元素则返回true。
步骤:
1)创建集合对象coll;
2)使用集合对象coll调用add()函数向集合中添加数据;
3)使用集合对象coll调用contains()函数判断集合某个数据是否在集合中,如果有返回true,否则返回false;
4)使用集合对象coll调用clear()函数清除集合中的所有数据;
5)使用集合对象coll调用isEmpty()函数判断集合中元素是否有数据,如果有数据则返回false,没有数据则返回true;
package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;
/*
*判断方法
*/
public class Collection ContainsAndIsEmptyDemo {
public static void main(String[] args) {
//创建集合对象
Collection coll=new ArrayList();
//给集合添加数据
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
//使用Collection接口中的contains()函数判断某个对象是否在集合中
//如果有,则返回true,如果没有,则返回false
boolean boo = coll.contains("aaa");
System.out.println(boo);
//输出集合数据
System.out.println(coll);
//判断集合中是否有数据,如果有数据则返回false,没有数据则返回true
boolean boo1 = coll.isEmpty();
System.out.println(boo1);
//清空集合中的数据
coll.clear();
boolean boo2 = coll.isEmpty();
System.out.println(boo2);
}
}
2.2.4、Collection接口中带All的方法
boolean addAll(Collectionc)表示把c集合中的元素全部添加到当前调用这个方法的集合中。
分析和步骤:
1)使用new关键字创建集合类ArrayList的两个对象coll和coll2,两个对象的类型是接口Collection;
2)使用coll和coll2对象分别调用add()函数给集合添加数据;
3)使用coll2对象调用addAll()函数,coll集合对象作为该函数的参数,最后输出coll2的结果;
代码实现如下:
package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;
/*
* Collection接口中addAll方法的演示
*/
public class Collection AddAllDemo {
public static void main(String[] args) {
/*
*由于Collection是接口,所以不能创建Collection接口的对象,
*但是我们可以使用new关键字创建Collection接口下面的任意一个类的对象,然后对象类型变为Collection
*/
Collection coll=new ArrayList();//这里发生多态了
//再创建一个集合对象
Collection coll2 = new ArrayList();
//使用coll对象调用add函数向集合中引用类型添加数据
coll.add("aaaa");
coll.add("bbbb");
coll.add("dddd");
coll.add("eeee");
//向集合coll2中添加数据
coll2.add("AAAA");
//将集合coll中的数据添加到集合coll2中
coll2.addAll(coll);
//输出集合中的数据
System.out.println(coll2);
}
}
说明:判断集合中是否包含指定集合中的所有元素。
containsAll()方法是要求作为参数传递的集合中的元素需要全部在调用这个方法的集合中存在,才会返回true。
分析和步骤:
1)使用new关键字创建集合类ArrayList的两个对象coll和coll2,两个对象的类型是接口Collection;
2)使用coll和coll2对象分别调用add()函数给集合添加数据;
3)使用coll对象调用containsAll()函数,coll2集合对象作为该函数的参数,最后输出布尔类型的返回结果;
package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;
/*
* Collection接口中containsAll方法的演示
*/
public class Collection ContainsAllDemo {
public static void main(String[] args) {
/*
*由于Collection是接口,所以不能创建Collection接口的对象,
*但是我们可以使用new关键字创建Collection接口下面的任意一个类的对象,然后对象类型变为Collection
*/
Collection coll=new ArrayList();//这里发生多态了
//再创建一个集合对象
Collection coll2=new ArrayList();
//使用coll对象调用add函数向集合中引用类型添加数据
coll.add("aaaa");
coll.add("bbbb");
coll.add("dddd");
coll.add("eeee");
//向集合coll2中添加数据
coll2.add("AAAA");
//将集合coll中的数据添加到集合coll2中
coll2.addAll(coll);
//coll集合:"aaaa" "bbbb" "dddd""eeee"
//coll2 集合:"AAAA" "aaaa" "bbbb""dddd" "eeee"
//判断集合coll中是否包含集合coll2中的所有集合,如果包含返回true,否则返回false
//boolean boo =coll.containsAll(coll2);//false 不包含
boolean boo =coll2.containsAll(coll);//true包含
//输出返回值
System.out.println(boo);
}
}
说明:
1)boolean removeAll(Collection c) :表示从调用这个函数执行的集合中删除当前集合与指定集合中共同的元素,删除交集;
2)boolean retainAll(Collection c) :表示从调用这个函数执行的集合中删除两个集合中不同的元素,也可以理解为保留两个集合中共有的元素,保留交集。
分析和步骤:
1)使用new关键字创建集合类ArrayList的两个对象coll和coll2,两个对象的类型是接口Collection;
2)使用coll和coll2对象分别调用add()函数给集合添加数据;
3)使用coll对象分别调用removeAll()和retainAll()函数,coll2集合对象作为该函数的参数,最后输出布尔类型的返回结果和两个集合对象coll和coll2;
public static void method_3() {
// 创建集合对象
Collection coll = new ArrayList();
Collection coll2 = new ArrayList();
coll.add("aaaa");
coll.add("bvvv");
coll.add("dddd");
coll2.add("aaaa");
coll2.add("dddd2");
/*
*coll.removeAll(coll2)
*是从coll集合中删除 coll与coll2中相同的元素(交集)
*/
/*
boolean b = coll.removeAll(coll2);
System.out.println(coll);
System.out.println(coll2);
System.out.println(b);
*/
/*
*coll.retainAll(coll2)
*是从coll中删除 coll与 coll2中不同的元素,也可以理解成保留2个集合的交集
*/
boolean b = coll.retainAll(coll2);
System.out.println(coll);
System.out.println(coll2);
System.out.println(b);
}
2.2.5、toArray()遍历集合
遍历就是指依次从容器中获取每一个容器中的对象元素。
问题1:我们之前直接通过输出集合的对象名比如:System.out.println(coll);就可以输出集合中的数据了,为什么还要遍历集合呢?
我们之前通过输出集合名的方式来输出集合中的数据的方法是可以将集合中的数据输出来,但是那些输出的都是将集合中的对象变成字符串然后拼接在一起输出的,这样输出就改变了原来对象的意思了,我们希望当时存储到集合中是对象,取出来的时候仍然是对象,这样不改变原来对象元素的意思,可以使用对象操作对象本身的函数或者属性。
问题2:现在会使用集合中的专用遍历方式吗?
不会。只会对数组进行遍历
在Collection集合中存在一个方法,可以把集合对象转为数组对象:
案例:对集合中的学生对象,进行遍历(集合转数组的方式实现)
分析和步骤:
1)定义一个Student类,在这个类中定义两个属性name和age;
2)在这个类中生成toString()函数,对外提供get和set方法;
3)在定义一个类,在这个类中创建集合对象stus;
4)使用集合对象stus调用add()函数向集合中添加学生对象;
5)使用集合对象stus调用toArray()函数将集合转换为数组;
6)使用for循环遍历数组,并根据数组名和下标输出对象即可;
package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;
import cn.xuexi.demo.Student;
/*
*遍历集合
*/
public class Collection ToArrayDemo {
public static void main(String[] args) {
//创建集合对象
Collection coll=new ArrayList();
//创建学生对象
Student s=new Student("张三",18);
Student s1=new Student("李四",19);
Student s2=new Student("王五",20);
Student s3=new Student("锁哥",21);
//将学生对象添加到集合中
coll.add(s);
coll.add(s1);
coll.add(s2);
coll.add(s3);
/*
*想要对集合进行遍历我们还没有学习,但是我们学习过怎样对数组进行遍历
*所以我们可以将集合转换为数组
*/
/*
int[] arr1={1,2,3};
int x=arr1[0];
String[] arr2={"ss","dd"};
Strings tr=arr2[0];
*/
Object[] arr = coll.toArray();
//遍历数组
for (int i =0; i < arr.length; i++) {
//取出数组中的对象数据
Object obj=arr[i];
//转换为Student类型
Student stu=(Student)obj;
//打印Student类中的属性值
// System.out.println(stu.getName()+"======"+stu.getAge());
/*
*由于以上发生多态,但是子类Student类中有非静态成员函数toString(),所以根据多态的特 点,
*对于非静态函数,如果子类有优先使用子类中的函数
*/
System.out.println(obj.toString());
}
}
}
说明:由于这里集合生成数组之后发生多态了,但是我们在Student类中复写了Object类中的toString()函数,所以根据多态的特点,对于非静态函数,如果子类有优先使用子类中的函数,直接输出生成数组名即可。
注意:利用toArray()方法转数组,并遍历数组,虽然可以遍历集合,但却不是我们常用的方式。一般不建议使用。
3、迭代器(遍历器)Iterator(掌握)
3.3.1、迭代器介绍
由于集合框架中的集合容器太多,而每个集合容器中保存的数据存储的方式都不一样。于是导致我们往出取数据的时候方式也完全不相同。
Java针对这些所有集合容器取出数据的方式进行共性的抽取,于是针对所有的集合定义了一个接口,在这个接口中描述了所有集合容器的共性遍历规则。
注意:对于集合取元素,无论是什么数据结构,最终共性的取出方式:
一个一个取,取之前先判断,有,取一个,没有,结束。
这种取出的共性方式:迭代。迭代可以理解为取出或者遍历。
而这个接口它就是Iterator,它中定义了集合最基本的遍历方式:
Iterator接口的迭代(取出、遍历)方式:
针对一个集合,需要遍历的时候,应该首先去判断集合中有没有元素(对象),有就取出这个元素,没有就不用再进行遍历了。
hasNext()函数表示判断容器中还有没有元素,如果有返回true,我们就可以根据这个返回的结果确定到底还要不要遍历这个集合容器
next()函数表示取出当前遍历到的那个元素。
void remove()表示删除当前迭代器对象指向的集合中的元素。
对于迭代器Iterator中的函数解释和运行原理如下图所示:
说明:可以把迭代器对象理解成为一个移动的光标,开始的时候,光标会在集合容器的最上面,然后如果使用迭代器对象调用hasNext()函数的时候,光标会指向集合中第一个元素,如果hasNext()函数返回true,则说明有元素可以遍历(迭代),则使用迭代器对象调用next()函数就会将当前光标所指向的元素取出来,如果调用remove()函数,就会删除当前光标所指向的元素。
每执行完一次next()函数,光标都会往下移动,直到移动到集合的最低端,找不到元素为止。移动到最底端代表着此迭代器对象也使用完毕。
如果还想再重新迭代该集合那么需要再根据此集合重新创建一个迭代器对象。
注意:在使用集合对象生成迭代器对象后,那么此时这个迭代器对象已经记录下来此时集合中的结构,在使用迭代器遍历的时候,一定记住不能使用集合的对象来对集合中的元素进行删除或者添加,如果要改动可以使用迭代器对象改动集合,如果要改动集合中的内容可以根据改动后的集合对象再重新生成迭代器对象。
3.3.2、迭代器的使用
分析:
注意:
在我们书写迭代器使用代码的时候,我们首先应该考略一个问题,如何获得迭代器对象?
其实通过以上的分析我们不难得知,要想获得迭代器对象必须得先创建一个集合的对象,然后通过集合对象调用Collection接口中的iterator()函数就可以生成迭代器对象,如下图所示:
说明:由于集合种类有很多,各不相同,所以迭代器对象也会有很多,针对不同集合获得不同的迭代器对象,但是最后使用迭代器对象调用Iterator迭代器中的函数实现的效果是一致的,没有区别,即:根据迭代器对象调用hasNext()函数查看集合容器中是否含有要遍历的元素,调用next()函数获取集合容器中的元素。
步骤:
1)使用new关键字创建集合类ArrayList的对象coll,对象的类型是接口Collection;
2)使用对象coll调用add()函数给集合添加数据;
3)以前我们都是根据集合对象名coll将集合中的数据一次性输出,而这里我们要先使用集合对象coll调用iterator()函数获得迭代器对象;
4)然后根据迭代器对象调用next()函数依次取出数据并输出;
5)如果多次调用next()函数有可能会发生异常,因为集合中的数据已经取完了,所以为了防止发生异常,我们在取数据之前使用hasNext()函数进行判断一下,没有数据就不用取数据了;
6)由于是多条语句,我们可以考略使用循环while或者for;
代码如下:
运行结果:
分析异常的原因:
说明:当迭代器对象指向集合时,可以获取集合中的元素,如果迭代器的光标移动集合的外边时,此时迭代器对象不再指向集合中的任何元素,会报NoSuchElementException没有这个元素异常。
解决方案:在使用next()函数获取集合中元素前,使用hasNext()判断集合中是否还有元素。
上述代码一条语句重复执行多次,我们可以考虑使用循环来控制执行的次数,循环条件是 迭代器对象.hasNext()为false时表示集合中没有元素可以获取了,循环条件迭代器对象.hasNext() 为true的时候说明还可以获取元素。
package cn.xuexi.iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
*演示迭代器的使用
*/
public class IteratorDemo {
public static void main(String[] args) {
//创建集合对象
Collection coll=new ArrayList();
//向集合中添加数据
coll.add("aaaa");
coll.add("bbbb");
coll.add("cccc");
//根据当前集合获取迭代器对象
Iteratorit = coll.iterator();
//取出数据
/*System.out.println(it.next());//it.next()表示获取迭代器对象指向集合中的数据
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());*/
//使用while循环遍历集合
while(it.hasNext())//it.hasNext()表示循环条件,如果为true,说明集合中还有元素可以获取,否则没有元素
{
//获取元素并输出
System.out.println(it.next());
}
/*
*注意:针对集合每次获取到的迭代器对象,使用完之后,迭代器中的隐式光标就已经到了集合的最后,这样就无法再去使用next获取集合中的元素。如果还要获取,需要重新在获取一个迭代器对象。
*/
//报找不到元素异常,对于it迭代器对象,它已经移动到集合中最后了,再找就没有元素了,只能重新获得迭代器对象
//System.out.println(it.next());
//使用for循环遍历集合 推荐开发使用
/*for (Iterator it2 = coll.iterator(); it2.hasNext();) {
System.out.println(it2.next());
}*/
}
}
注意:针对集合每次获取到的迭代器对象,使用完之后,迭代器中的隐式光标就已经到了集合的最后,这样就
无法再去使用next获取集合中的元素。如果还要获取,需要重新在获取一个迭代器对象。
while循环的迭代和for循环的迭代有什么不同?
while循环的迭代,由于初始化迭代器对象在while循环上面,在整个while循环结束后,迭代器对象还可以继续使用,但是集合中已经没有数据了,如果还仍然使用迭代器对象继续获取数据,会报异常,如果还要获取,需要重新在获取一个迭代器对象。所以对于while循环当迭代器对象使用完之后,迭代器就会变成一个没有用的垃圾,占内存。
对于for循环的迭代,由于初始化迭代器对象在for循环小括号中,在整个for循环结束后,迭代器对象就不能继续使用,也不会占内存,所以建议大家以后在开发中使用迭代器遍历集合最好使用for循环。
总结:在开发中,建议大家使用迭代器遍历集合的时候最好使用for循环。
3.3.3、迭代器注意细节
需求:遍历集合,遇到"abc"就把它删除。
分析和步骤:
1)使用new关键字创建集合类ArrayList的对象coll,对象的类型是接口Collection;
2)使用集合对象coll调用add()函数给集合中添加数据;
3)使用for循环遍历集合,取出每个元素,进行判断,只要当前取出的这个元素是"abc",就把它从集合中删除;
4)在for循环的初始化值位置上使用集合对象coll获取迭代器对象;
5)使用迭代器中的next()函数获取数据赋值给Object类型;
6)使用判断结构对取出的数据和字符串”abc”进行判断,如果找到,则使用迭代器对象调用迭代器中的remove()函数进行删除,不要使用集合中的remove(obj)函数,否则会报异常;
/*
*需求:遍历集合,遇到"abc"就把它删除。
*/
public class IteratorDemo2 {
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("abc");
coll.add("bbbbb");
coll.add("dddd");
coll.add("xyz");
coll.add("ABC");
/*
*遍历集合,取出每个元素,进行判断,只要当前取出的这个元素是"abc"
*就把它从集合中删除
*/
for( Iterator it = coll.iterator(); it.hasNext(); ){
//取出这个元素进行判断
Object obj = it.next();
if( obj.equals("abc") ){
/*
*当我们使用迭代器对集合中的元素进行迭代的时候,不允许使用集合自身的增删函数
*对集合中的元素进行操作。 如果真的需要删除,这时只能使用迭代器自身的remove方法
*/
//coll.remove(obj);
it.remove();
}
}
System.out.println(coll);
}
}
说明:如果使用集合中的remove(obj)函数进行删除,为什么会报异常?
由于迭代器对象是基于集合而来的,如果已经获取到了迭代器对象,就可以使用迭代器对象遍历集合,而此时在遍历集合的时候,如果使用集合对象调用集合中的函数对集合进行增删操作,那么对于迭代器对象而言就会导致最开始生成迭代器对象和修改集合之后不一样,而在java中是不允许这样操作的,如果想要在迭代集合的时候删除集合中的元素可以使用迭代器Iterator中的remove()函数。
总结:
1、使用迭代器对集合进行迭代的时候,不要使用集合自身的功能(函数)对集合进行增删操作;
2、所有的迭代器当迭代结束之后,那么这个迭代器对象(隐式光标)就位于集合的最后;
3、使用迭代器迭代集合的时候,每一个hasNext()方法都对应一个next()函数,不要一个hasNext()方法对应多个next()函数。
如下图所示,就是一个hasNext()函数对应多个next()函数,使用是错误的。
4.可以使用增强for循环遍历集合更加简单一些;
但是使用增强for循环的时候需要注意集合中的数据类型是Object,因为集合中可以存储各种引用类型数据,而Object类是所有引用类型数据的父类。
代码演示如下:
4、集合的细节
集合的细节:
1)集合中正常情况下是不能存储基本类型数据,但是在JDK1.5后可以直接在add方法中书写基本类型数据,因为底层在操作时会对基本类型数据进行装箱。
2)集合中存储的任何类型的元素,在存储到集合中时,全部都会转为Object类型;
3)从集合中取出元素时,取出的元素类型全部都是Object类型,如果想要使用类中特有的成员时,需要向下转型;
例如上述存储在集合中的自定义Student类,想要使用Student类中的特有的get和set函数:
package cn.xuexi.iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import cn.xuexi.demo.Student;
public class IteratorDemo1 {
public static void main(String[] args) {
//创建集合类对象
Collection coll=new ArrayList();
//向集合中添加数据
coll.add(new Student("张三",19));
coll.add("aaaa");
//遍历取出集合中的数据
for(Iteratorit = coll.iterator(); it.hasNext();) {
Object obj = it.next();
/*
*想通过取出的对象调用Student类中特有的getName()和getAge()函数获得属性值
*由于getName()和getAge()函数是Student类中的特有的函数,而从集合中取出的数据
*都是Object类型,要想使用子类Student特有的函数,必须向下转型,向下转型有风险
*使用需谨慎,使用instanceof判断转型的数据类型
*/
if(obj instanceof Student)
{
//说明是Student类型
Student stu=(Student)obj;
System.out.println(stu.getName()+"====="+stu.getAge());
}
}
}
}
4)集合容器是用来保存对象的。而真正给集合中保存的不是当前那个对象,而是对象在堆内存中的内存地址。
给集合中保存自定义对象:
a.使用上述自定义的Student类,在类中定义name和age属性,生成get和set方法;
b.随便定义一个测试类,在main函数中创建集合对象,同时创建Student类的对象;
c.将Student类的对象添加到集合中,并迭代集合,遍历输出结果,会发现打印的是Student类的对象的地址值
d.如果在Student类中复写toString()函数就会打印name和age的属性值;
代码如下:
自定义学生类:
package cn.xuexi.demo;
//描述学生
public class Student {
//属性
String name;
int age;
//定义构造函数给属性初始化值
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//给属性生成get和set方法
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;
}
//生成toString()函数
public StringtoString() {
return "Student [name=" + name +", age=" + age + "]";
}*/
}
测试类:
package cn.xuexi.iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import cn.xuexi.demo.Student;
public class IteratorDemo2 {
public static void main(String[] args) {
//创建集合类对象
Collection coll=new ArrayList();
//向集合中添加数据
coll.add(new Student("张三",19));
//遍历取出集合中的数据
for(Iteratorit = coll.iterator(); it.hasNext();) {
/*
*如果自定义Student类中不复写toString()函数那么就会输出一串内存地址
* cn.xuexi.demo.Student@6d9dd520
*/
System.out.println(it.next());
}
}
}
内存图解如下图所示:
5、集合使用的步骤
步骤总结:
1、创建集合
2、添加元素
3、遍历集合:
1)获取迭代器对象;
2)循环迭代集合;