Java面向对象——集合框架(Collection)
面向对象
集合概述:
集合的特点:Java是面向对象语言,如果我们要针对多个对象进行操作,就必须对多个对象进行存储。
而对多个元素进行存储,前面我们学习过数组,数组的弊端,长度固定。这样,数组将不能满足变化的要求。所以,Java就提供了集合供我们使用。
集合和数组的区别:长度可以发生改变。
只能存储对象。
可以存储多种类型对象(一般存储的还是同一种,因为1.5JDK的新特性 泛型)。长度问题
数组固定。
集合可变。
存储元素问题
数组可以是基本类型,也可以是引用类型。
集合只能是引用类型。(JDK1.5以后还可以存储基本数据类型,因为JDK1.5自动装箱拆箱)
是否同一类型
数组元素类型一致。
集合元素类型可以不一致。(建议还是同一种类型,因为JDK1.5出现了泛型)
功能是否一致
数组只能对数据进行存取操作,当然删除数组中的元素还可以删除,就是null。
集合不但可以对数据进行基本操作,还提供了更强大的功能,比如删除 修改...。
集合体系的由来
集合是存储多个元素的容器,但是,由于数据结构不同,Java就提供了多种集合类。
而这多种集合类有共性的功能,所以,通过不断的向上抽取,最终形成了集合体系
结构。
为什么会出现这么多的容器呢?
如何学习和使用一个继承体系呢?数据结构:数据存储的方式。因为每一个容器对数据的存储方式都有不同,这个存储方式称之为:数据结构。
学习顶层:因为顶层定义的是共性内容。
使用底层:因为底层才是具体的实现。
简单一句话:参阅顶层内容,建立底层对象。
Collection:定义了集合框架的共性功能。|------List(列表):元素是有序的,元素可以重复,因为该集合体系有索引。
|--ArrayList:底层是数组数据结构,查询速度很快,但是增删稍慢,线程不同步,默认10个元素。(线程不同步)
|--LinkedList:底层是链表数据结构,查询很慢,增删速度很快。(线程不同步)
|--Vector:底层是数组数据结构,和ArrayList一样,查询,增删,都很慢,Vector是1.0出现,ArrayList是1.2出现,(线程同步)但已经不用了。
|------Set(集):元素是无序的(存入和取出顺序不一定一致),元素不可以重复。
|--HashSet:底层数据结构是哈希表。线程是不同步的。
采用散列函数对元素进行排序(Asiic),是专门为快速查询而设计的。存入HashSet的对象必须定义hashCode方法。
|--LinkedHashSet:有序。
内部使用散列以加快查询速度,同时使用链表维护元素插入的次序,在使用迭代器遍历Set时,结果会按元素插入的次序显示。
|--TreeSet:底层的数据结构是二叉树。线程是不同步的。
对Set集合中的元素的进行指定(我们指定的比较器)顺序的排序。不同步。TreeSet底层的数据结构就是二叉树。
采用红黑树的数据结构进行排序元素,使用它可以从Set中提取有序(升序或者降序)的序列。
需要注意的是,存入自定义类时,TreeSet需要维护元素的存储顺序,因此自定义类要实现Comparable接口并定义compareTo方法。
注意:集合只能保存引用数据类型,也就是存储的是对象的地址值,而不是对象本身。集合中的元素相当于引用类型变量。
注意:如果使用的集合涉及到了频繁的插入,建议使用LinkedList。
Collection
布尔型 add(E e)
此处的E现在可以当成Object去理解
将指定的元素添加到此列表的尾部。
布尔型
addAll(Collection<? extendsE> c)
将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
无返回值
clear()
移除此列表中的所有元素。
布尔型
contains(Object o)
如果此列表中包含指定的元素,则返回true。
布尔型
containsAll(Collection<?> c)
如果此 collection 包含指定 collection 中的所有元素,则返回true。
布尔型
equals(Object o)
比较此 collection 与指定对象是否相等。
整数
hashCode()
返回此 collection 的哈希码值。
布尔型 isEmpty()
如果此 collection 不包含元素,则返回true。
迭代器 iterator()
返回在此 collection 的元素上进行迭代的迭代器。
布尔型
remove(Object o)
从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
布尔型
removeAll(Collection<?> c)
移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
布尔型 retainAll(Collection<?> c)
仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
整数
size()
返回此 collection 中的元素数。
对象[] toArray()
返回包含此 collection 中所有元素的数组。
<T> T[]
toArray(T[] a)
返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。
ArrayList特有方法:既然是对数据进行操作的,当然就有 增、删、改、查 这四个方法。
无返回值 add(int index,E element)
将指定的元素插入此列表中的指定位置。
布尔型 addAll(Collection<? extendsE> c)
按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。
布尔值 addAll(int index,Collection<? extendsE> c)
从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
E
get(int index)
返回此列表中指定位置上的元素。
整数 indexOf(Object o)
返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。
整数 lastIndexOf(Objecto)
返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
E
set(int index,Eelement)
用指定的元素替代此列表中指定位置上的元素。代码示例:
importjava.util.List;
import java.util.ArrayList;
public class Test{
public static voidmain(String[] args){
ArrayList al =newArrayList();
al.add("黑马程序员——Java01");//添加了一个元素
al.add("黑马程序员——Java02");
al.add("黑马程序员——Java03");
al.add("黑马程序员——Java04");
sop(al.get(1));
al.remove("黑马程序员——Java04");//删除一个元素
sop(al.size());//打印下集合的长度 结果为3.因为删了一个
al.clear();//清空集合
sop(al.contains("黑马程序员——Java03"));
sop(al.isEmpty);
method();
}
public static voidmethod(){
List list1 =newArrayList();
list1.add("黑马程序员——Java01");
list1.add("黑马程序员——Java02");
list1.add("黑马程序员——Java03");
list1.add("黑马程序员——Java04");
List list2 =newArrayList();
list2.add("黑马程序员——Java01");
list2.add("黑马程序员——Java02");
list2.add("黑马程序员——Java05");
list2.add("黑马程序员——Java06");
//list1.retainAll(list2);//取焦急。拿list1元素跟list2的元素比,如果相同就保留。调用父类的方法
//sop(list1);
list1.removeAll(list2);//删除焦急。拿list1的元素跟list2的元素比,如果相同就删除。调用父类的方法
sop(list1);
}
public static voidsop(Object obj){
System.out.println(obj);
}
}
注意:Test.java 使用了未经检查或不安全的操作。 注意:要了解详细信息,请使用 -Xlint:unchecked 重新编译。
集合注意:
1、直接存储基本类型值也是可以的,因为JDK1.5后,有自动装箱技术,会将基本数据类转换成数据对象。JDK1.4绝对不行,因为集合中存放的对象的引用,当直接存放基本类型值的时候,会将这个基本类型值变成一个对象(自动装箱)。
2、集合对象中存储的其实都是元素对象的引用。
3、add方法的参数是Object类型可以接受所有类型的对象。但会出现向上转型,取出元素时的类型还是Object,不能使用具体对象的特有内容,想要是有特有内容,必须向下转型。集合框架中存放的都是对象的地址。当我们想用对象的特有方法的时候必须向下转型。
当我们想直接打印一个集合,其实是调用了这个对象的toString方法,当我们要打印一个对象的长度的时候,首先我们会想到length方法。但是由于我们添加数据的时候用的add方法,而add方法的参数类型是Object,也就说把存进去的数据向上转型了。但是我们都知道Object是没有length方法,此时无法使用length方法。那么就要向下转型才可以,只有使用子类的特有方法size。
迭代器(Iterator)迭代时注意:在迭代时候,不可以通过集合对象的方法操作集合中的元素,因为会发生 ConcurrenModificationException异常。所以在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作1、什么是迭代器?其实就是集合的取出元素的方式。
就把取出方式定义在集合的内部,这样取出方式就可以直接访问结合内容的元素。那么取出方式就定义成了内部类。
而每一个容器的数据结构不同,所以取出的动作细节也不一样,但是都有共性内容:取出。那么可以写共性取出。
那么这些内部类都符合一个规则。该规则是Iterator。
如果想要其他的操作,如添加、修改等,就需要使用其子接口,ListIterator。如何获取集合的取出对象呢?
通过一个对外提供的方法:iterator()
Iterator
迭代器的使用
1.使用步骤1)通过集合对象获取迭代器对象。2)通过迭代器对象判断。3)通过迭代器对象获取。
2.迭代器原理
由于多种集合的数据结构不同,所以存储方式不同,所以,取出方式也不同。这个时候,我们就把判断和获取功能定义在了一个接口中,将来,遍历哪种
集合的时候,只要该集合内部实现这个接口即可。
3.集合的常见使用步骤
1)创建集合对象。
2)创建元素对象。
3)把元素添加到集合中。
4)遍历集合。