目录
简介
- Java中有三大类集合:List(列表)、Set(集合)、Map(映射),三者都属于接口类,分别有各自的实现。
- Collection为基本的集合接口,声明了集合的通用方法,List和Set都是继承于此。
- add(Object o):新增对象
- set(int index, Object o):设置对象值
- remove(Object o):删除对象
- contains(Object o):检查是否包含此对象
- size():返回元素个数
- iterator():返回一个迭代器,用来遍历集合元素
- toArray():集合转换成数组,数组中是全部元素
- 继承关系graph TB; Iterator(Iterator) --> Collection(Collection) Iterator --> ListIterator(ListIterator) Iterator --> Map(Map) Collection --> Set(Set) Collection --> List(List) ListIterator --> List Set --> HashSet[HashSet] Set --> TreeSet[TreeSet] HashSet --> LinkedHashSet[LinkedHashSet] List --> ArrayList[ArrayList] List --> LinkedList[LinkedList] Map --> HashMap[HashMap] Map --> TreeMap[TreeMap] HashMap --> LinkedHashMap[LinkedHashMap]
List
List的最大特点就是保证了元素的顺序,使用Iterator可以方便的遍历、增删列表中的元素。两个实现都是线程不安全的,但是效率高;Vector虽然线程安全,但是方法中加synchronized导致阻塞,效率低。
- ArrayList
由数组实现的List,可以高效的对元素进行随机访问,但是往数组内部增删则效率会慢很多(因为涉及到数组中元素的移动),使用Iterator最好用来遍历,而非增删数据。- 优点:实现了基于动态数组的数据结构,地址连续,查询效率高。
- 缺点:因为地址连续,要在列表中增删数据会导致其他数据移动,所以插入效率低。
- 使用场景:多查询访问的用,或者在列表后方添加数据的场景。
- LinkedList
使用链表实现的List,由于没有固定的内存列表,而是元素首尾互相记录地址来“链接”,所以元素内部的增删操作效率会高很多,相应的随机访问则会慢很多。由于双向链表的特性,LinkedList可以作为堆栈、队列和双向队列来使用。- 优点:基于链表的数据结构,地址随意,开辟新空间不需要连续地址,对于增删只需要修改内存地址即可。
- 缺点:由于地址不连续,所以在查询的时候,需要移动指针,性能较低。
- 使用场景:适用于头尾操作或者插入指定位置的场景。
- 常用方法:addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()
- Vector
也是由数组实现的动态列表,但是比较老,由于所有操作都使用线程同步,所以效率较低。与List不同的是在空间不够时,扩容方式不一样,且Vector可以设置增长因子。所以Vector适合在多线程场景或数据量较大的场景。
Set
具有和Collection一样的接口,只是行为不同,体现了继承与多态的典型应用。存入Set中的每个元素都是唯一的,加入的元素需要重写equals保证对象唯一。Set接口不保证维护元素次序。
- HashSet
使用hash表记录的元素集合,内部也是列表,专门快速查询设计的。填充的元素需要重写hashCode方法来对比检查是否存在。允许key的值为null,但是也仅支持一个。- 使用场景:查找较多且不关心顺序的场景
- LinkedHashSet
在HashSet的基础上添加了链表,用来维护元素插入顺序,使用迭代器遍历都时候会按照元素插入顺序。- 使用场景:查找较多且关心插入顺序的场景(比较少)
- TreeSet
使用红黑树结构记录的集合,因为树原生具有次序,所以具有次序(为自定义顺序,非插入顺序)。- 使用场景:需要自定义排序功能的场景
Map
Map需要提供键和值作为映射关系进行关联,可以通过键来获取值。虽然更加灵活,功能更加丰富,但是Map的效率也是比较低的。同时Map的实现是线程非安全的,虽然Hashtable线程安全(方法加synchronized),但是效率低,推荐使用ConcurrentHashMap。
- HashMap
基于列表、散列表、链表和红黑树(Java8)的实现,最优场景下开销都是固定的。- 使用场景:较多插入、删除、定位元素
- 获取数据:
- map.keySet()、map.values():以集合形式获取Map的所有key或value
- map.get(key):根据key值获取value值
- 迭代器遍历:
// 迭代器 Iterator<Entry<Object, Object>> iterator = map.entrySet().iterator(); // 直接遍历 for (Entry<Object, Object> entry : map.entrySet()) { entry.getKey(); entry.getValue(); }
- LinkedHashMap
在HashMap的基础上,添加了维护插入顺序的链表用来在迭代中返回插入顺序,同时因为使用链表,迭代的效率会更加的快。 - TreeMap
基于红黑树数据结构实现。在插入数据的时候会根据排序算法对数据进行排序(Comparabel或Comparator)。- 使用场景:需要自然排序或者自定义排序顺序遍历键
互相转换
sour\dest | to List | to Array | to Set |
---|---|---|---|
List | null | list.toArray(new Object[0]) | new HashSet<>(list) |
Array | new ArrayList(Arrays.asList(array)) | null | new HashSet<>(Arrays.asList(array)) |
Set | new ArrayList<>(set) | set.toArray(new Object[0]) | null |
Map | new ArrayList<>(map.keySet()/values()) | map.keySet().toArray(new Object[0]) | new HashSet<>(map.values()) |