第一讲:体系概述
一、概述
1、 作用:用于存放对象的容器
2、 特点:只用于存储对象,集合长度可变,集合可以存储不同类型的对象;
3、 与数组的区别:虽然数据也可以存储对象,但数组的长度是固定的,而集合长度是可变的,集合类的出现可以解决现实生活中数量不确定的问题;
4、 常用的集合类及结构
第二讲:共性方法
集合实现了Collection接口,Collection接口声明了如下常用方法:
1) 向集合中添加元素:add(Object obj)、addAll()
add()方法用于向集合中添加对象,实际添加的并不是对象本身,而是将对象的地址添加到了集合中。如下:是将hello_1、hello_2、hello_3这三个字符串对象在堆内存中的地址添加给了ar1集合。
总结:
- add(Object obj)方法的参数是Object,以便于接收任意类型对象;
- 集合中存储的都是对象的引用或者地址;
2) 删除集合中元素:remove(Object obj)
3) 判断元素是否存在于集合中
4) 取两个集合的交集:retainAll(Collection c)
ar1.retainAll(ar2); //获取ar1和ar2中共同的元素,并最终赋给ar1。
5) 去掉交集:removeAll(),去掉两个集合中的共同元素
ar1.removeAll(ar2); //去掉ar1中与ar2相同的元素。
第三讲:迭代器
概念:定义在集合内部的,用于取出集合中的元素的方式;
定义迭代器来取集合中元素的原因:不同的集合,数据存放的结构不同,取的动作细节也不同,因此,不能简单的定义一个函数来读取所以集合中的元素,需要根据不同集合的特性定义不同的元素读取方法,这些方法被封装在了集合的内部类中。当我们需要调用集合的元素时,只需利用内部类对象来调用这些方法即可,而Collection接口为所以继承自Collection接口的集合提供了一个获取内部类对象的方法:iterator()。
ar1.iterator()——获取集合ar1的迭代器。
iterator()特性:该方法返回了迭代器(Iterator<E>接口)的对象,Iterator<E>接口中声明了三个方法:
- boolean hasNext()——判断集合中是否仍有元素可以迭代,是返回true,否则返回false;
ar1.hasNext()——判断集合ar1中是否仍有元素和迭代。
- E next()——返回迭代的下一个元素,即集合的下一个元素;
ar1.next()——返回ar1迭代的下一个元素。
- Void remove()——从迭代器指向的collection中移除迭代器返回的最后一个元素(可操作)。
第四讲:List集合共性方法
List和Set都是Collection下的类,两者的区别如下:
- List:元素是有序的,元素可以重复,因为该集合体系有索引;
- Set:元素是无序的,元素不可以重复;
List特性:凡是可以操作角标的方法都是该体系特有的方法;
List方法:
1) 增
add(index,element)——在指定位置添加元素
addAll(index,Collection)——在指定位置添加元素集
2) 删
remove(index)——删除指定位置的元素
3) 改
Set(index,element)——将指定位置元素替换成element
4) 查
Get(index)——获取指定位置的元素;
subList(from,to)——获取指定位置区间的元素
listIterator()——利用迭代器获取元素
迭代器使用注意事项
在迭代过程中,对集合元素进行添加或删除操作时,不能同时使用迭代器和集合引用对集合元素进行添加或删除操作,如下代码会出现异常:
正确写法如下:
第五讲:ListIterator
概述:ListIterator是List集合特有的迭代器,是Iterator的子接口。
ListIterator的由来:在迭代时,同样不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。所以,在迭代时只能用迭代器的方式操作元素,可是Iterator中的方法是有限的,只能对集合中元素进行判断、取出、删除的操作,如果想要进行其他的操作,如,添加、修改等,就需要定义Iterator的子接口,并在该接口中增加需要的方法,该自接口为ListIterator。
获取方法:该接口只能通过List集合的listIterator()方法获取。使用实例如下:
第六讲:List集合具体对象的特点
ArrayList:底层的数据结构使用的是数组结构,特点:查询速度快,但增删稍慢,线程不同步,但java中给出了便捷的解决方案;
LinkedList:底层使用的是链表数据结构,特点:增删速度很快,但查询稍慢;
Vector:底层是数组数据结构,线程同步,已经被ArrayList替代。
第七讲:Vector中的枚举
Vector有一个特殊的取出元素方法:枚举法Enumeration
枚举法和迭代器很像,他们的功能是重复的。
因为枚举法的名称以及方法名称都过长,所以就被后来的迭代器给取代了。枚举法读取元素方法如下:
第八讲:LinkedList
1、LinkedList的特有方法:
添加:addFirst()、addLast()
获取:getFirst()、getLast()——获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException异常
删除:removeFirst()、removeLast()——获取元素,但元素被删除。如果集合中没有元素,会出现NoSuchElementException异常
2、JDK1.6出现替代方法,可以避免因集合中没有元素出现的异常
添加:offerFirst()、offerLast()
获取:peekFirst()、peekLast()——获取元素,但元素不被删除。如果集合中没有元素,会返回null,不会抛出异常;
删除:pollFirst()、peekLast ()——获取元素,但元素被删除。如果集合中没有元素,会返回null,不会抛出异常;
练习:使用LinkedList模拟一个堆栈或者队列数据结构
堆栈:先进后出,如同一个杯子
队列:先进先出,如同一个水管
思路:利用LinkedList数据结构特性,封装一个符合自己要求的数据结构,这个数据结构向外提供添加、获取、删除等操作。
练习一:去除ArrayList集合中的重复元素
思路:创建一个新的集合,从老集合中读取元素并添加到新集合中,并将新集合地址赋给老集合,在添加之前先判断新集合中是否已经有此元素,若有,则不添加;否则添加。
练习二:将自定义对象作为元素存到ArrayList集合中,并去除重复元素
1、思路:
1)描述一个对象,将数据封装进这个对象中,以人为例;
2)定义一个容器,将人存入;
3)去除重复的人——姓名、年龄都相同的为同一个人;
2、实现如下:
3、注意事项:
1)集合中remove(Object obj)方法的实现原理是:遍历集合,查找要删除的对象,过程需要调用equals方法进行判断集合中是否存在要删除的元素,因此,需要根据实际的情况重写equals。
2)集合中contains(Object obj)方法的实现原理:遍历集合,调用equals方法进行判断,集合中的元素是否存在和obj相同的元素,因此,需要根据实际的情况重写equals。
第12讲 HashSet
Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。在添加元素时,判断集合中是否已经存在与此对象地址一致的,若存在,则比较他们的值是否一致,若一致,则不添加此元素;若不一致,则在同地址值下面添加新对象。
Set集合的功能和Collection是一致的。
1、 HashSet
底层数据结构是哈希表。HashSet保证元素唯一性的方法如下:
通过元素的两个方法,hashCode和equals来完成。如果元素的HashCode值相同,才会判断equals是否为true;如果元素的HashCode值不同,不会调用equals。
所以在自定义对象的时候,通常需要重写hashCode和equals方法,重写示例如下:
注意:对于判断元素是否存在,以及操作,HashSet依赖的方法是元素的hashCode和equals;ArrayList依赖的只有equals。
小知识点总结
1、集合都有对集合中元素进行增、删、改、查的方法,不同的集合子类还有各自不同的操作方法。如List的特有方法有:add(index,element)、remove(index)、Set(index,element)、Get(index)等。
2、迭代器
迭代器就像一个连接集合和外部的工具,用于外部读取集合内部的元素。
它将读取元素的具体细节动作封装在集合内部,而给外部提供了共性的操作,即,获取迭代器对象、调用方法读取集合中的元素。
3、读取集合中元素的方法有三种:
1)利用remove()方法遍历集合中的元素
2)利用迭代器读取元素
3)利用枚举法读取集合中的元素——仅限于Vector
4、使用ArrayList或LinkedList的情景判断
当应用中需要频繁查询元素,但较少增删元素时,建议使用ArrayList;当需要频繁增删操作,但较少查询元素时,建议使用LinkedList;当既要频繁查询又要增删元素时,建议使用ArrayList。
5、自定义数据结构
我们可以利用已有的数据结构来自定义自己需要的数据结构,自定义该数据结构的方法,以此来限制或扩展数据结构的特性。如自定义该数据结构的增、删、改、查等功能。