如果一个Java对象可以在内部持有若干其他Java对象,并对外提供访问接口,我们把这种Java对象称为集合。
Java集合框架

Collection
Java标准库自带的java.util包提供了集合类:Collection,它是所有其他集合类的根接口。在Collection的基础上,Java的java.util包主要提供了以下三种类型的集合:
List:一种有序列表的集合,例如,按索引排列的Student的List;Set:一种保证没有重复元素的集合,例如,所有无重复名称的Student的Set;Map:一种通过键值(key-value)查找的映射表集合,例如,根据Student的name查找对应Student的Map。
Java访问集合总是通过统一的方式——迭代器(Iterator)来实现,好处在于无需知道集合内部元素是按什么方式存储的。
遗留类、遗留接口不应该继续使用:
Hashtable:一种线程安全的Map实现;Vector:一种线程安全的List实现;Stack:基于Vector实现的LIFO的栈。Enumeration<E>:已被Iterator<E>取代。
List
List是一种有序链表,有序结构,类似数组。
需要增删元素的有序列表,使用最多的是ArrayList,ArrayList在内部使用了数组来存储所有元素。
ArrayList把添加和删除的操作封装起来,操作List类似于操作数组,却不用关心内部元素如何移动。
考察List<E>接口,可以看到几个主要的接口方法:
- 在末尾添加一个元素:
void add(E e) - 在指定索引添加一个元素:
void add(int index, E e) - 删除指定索引的元素:
int remove(int index) - 删除某个元素:
int remove(Object e) - 获取指定索引的元素:
E get(int index) - 获取链表大小(包含元素的个数):
int size()
LinkedList通过“链表”也实现了List接口。
比较ArrayList和LinkedList:
| ArrayList | LinkedList | |
|---|---|---|
| 访问指定元素 | 速度很快 | 需要从头开始查找元素 |
| 添加元素到末尾 | 速度很快 | 速度很快 |
| 在指定位置添加/删除 | 需要移动元素 | 不需要移动元素 |
| 内存占用 | 少 | 较大 |
创建List
1 | import java.util.ArrayList; |
根据给定元素快速创建List:
1 | List<Integer> list = List.of(1, 2, 5); |
List.of()方法不接受null值,如果传入null,会抛出NullPointerException异常。
遍历List
和数组类型,我们要遍历一个List,完全可以用for循环根据索引配合get(int)方法遍历:
1 | import java.util.List; |
List内部并不是通过==判断两个元素是否相等,而是使用equals()方法判断两个元素是否相等。
equals()方法要求我们必须满足以下条件:
自反性(Reflexive):对于非
null的x来说,x.equals(x)必须返回true;对称性(Symmetric):对于非
null的x和y来说,如果x.equals(y)为true,则y.equals(x)也必须为true;传递性(Transitive):对于非
null的x、y和z来说,如果x.equals(y)为true,y.equals(z)也为true,那么x.equals(z)也必须为true;一致性(Consistent):对于非
null的x和y来说,只要x和y状态不变,则x.equals(y)总是一致地返回true或者false;对
null的比较:即x.equals(null)永远返回false。
一般遍历数组都是采用for循环,推荐用迭代器Iterator来访问List,采用迭代器遍历集合框架,它是一个对象,实现了Iterator 接口或ListIterator接口。
迭代器,使你能够通过循环来得到或删除集合的元素。ListIterator 继承了Iterator,以允许双向遍历列表和修改元素。
遍历 ArrayList
1 | import java.util.*; |
第三种方法是采用迭代器的方法,该方法可以不用担心在遍历的过程中超出集合的长度。
遍历Map
1 | import java.util.*; |
Set
Set<Map.Entry<K,V>> entrySet() //返回映射所包含的映射关系的Set集合(一个关系就是一个键-值对),就是把(key-value)作为一个整体一对一对地存放到Set集合当中的。正确使用Map必须保证:
- 作为
key的对象必须正确覆写equals()方法,相等的两个key实例调用equals()必须返回true; - 作为
key的对象还必须正确覆写hashCode()方法,且hashCode()方法要严格遵循以下规范:
- 如果两个对象相等,则两个对象的
hashCode()必须相等; - 如果两个对象不相等,则两个对象的
hashCode()尽量不要相等。
EnumMap
如果作为key的对象是enum类型,那么,还可以使用Java集合库提供的一种EnumMap,它在内部以一个非常紧凑的数组存储value,并且根据enum类型的key直接定位到内部数组的索引,并不需要计算hashCode(),不但效率最高,而且没有额外的空间浪费。
如果Map的key是enum类型,推荐使用EnumMap,既保证速度,也不浪费空间。
使用EnumMap的时候,根据面向抽象编程的原则,应持有Map接口。
TreeMap
一种Map,它在内部会对Key进行排序,这种Map就是SortedMap。注意到SortedMap是接口,它的实现类是TreeMap。
1 | ┌───┐ |
SortedMap保证遍历时以Key的顺序来进行排序。例如,放入的Key是"apple"、"pear"、"orange",遍历的顺序一定是"apple"、"orange"、"pear",因为String默认按字母排序。
发布时间: 2019-08-18
最后更新: 2019-08-31
本文链接: https://juoyo.github.io/posts/c9981ec.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!