Set、List和Map是java容器框架的三个最重要的接口。
- List提供了一个有序且有索引的容器,它允许重复值的出现。
- Set提供了一个无序的唯一对象的容器,也就是说Set不允许重复值。
- Map提供了一个基于键值对以及哈希的数据结构。
- Set 集合类似于一个罐子,把一个对象添加到Set集合时,Set集合无法记住添加这个元素的顺序,所以Set里的元素不能重复(否则系统无法准确识别这个元素)
- List集合非常像一个数组,它可以记住每次添加元素的顺序,只是List长度可变。
- Map集合也像一个罐子,只是它里面的每项数据都由两个值组成。
容器API里都有很多现成的实现
- List最常出现的实现类有ArrayList和LinkedList
- Set最常出现的实现类有HashSet、LinkedHashSet和TreeSet
- Map最常出现的实现类有HashMap、LinkedHashMap、Hashtable和TreeMap
Set vs List vs Map
前面提到了,Set、List和Map都是接口,它们定义了核心约束,比如一个Set约束说明了它不能包含重复值。下面我们就不同的指标对List、Set和Map进行对比。
1.重复对象
Java里List和Set接口的最主要的区别就在于List允许有重复对象而Set不允许重复对象。所有的Set实现都必须遵循这一约束。Map的每个Entry都持有两个对象都持有两个对象,也就是一个键一个值,Map可能会持有相同的值对象但键对象必须是唯一的。
2.排序
List和Set的另一个关键区别是List是一个有序容器,List保持了每个元素的插入顺序。Set是一无序容器,你无法保证每个元素的存储顺序。但是某些Set实现比如LinkedHashSet还是保持了每个元素的插入顺序。此外SortedSet和SortedMap比如TreeSet和TreeMap也通过Comparator或者Comparable维护了一个排序顺序。
3.空元素
List允许空元素,你可以在一个List里同时拥有很多null对象——因为它还允许重复元素。由于不允许重复的限制,Set最多只允许一个null元素。而Map里你可以拥有随意个null值但最多只能有一个null值。值得注意的是Hashtable既不允许null键也不允许null值,但HashMap允许任意数量的null值和最多一个null键。
4.流行实现
- List接口最流行的几个实现类是ArrayList、LinkedList和Vector。ArrayList最为流行,它提供了使用索引的随意访问,而LinkedList则对于经常要从List中添加或删除元素的场合更为合适。Vector是ArrayList的一个提供了同步功能的副本(功能上这样讲,但内部实现不是基于ArrayList实现)。
- Set接口中最流行的几个实现类是HashSet、LinkedHashSet以及TreeSet。其中HashSet不能提供任何排序保证,LinkedHashSet除了提供Set接口的唯一性之外还提供了元素的有序性,TreeSet实现了SortedSet接口,因此TreeSet是一个根据compare()和compareTo()的定义进行排序的有序容器。
- Map接口最流行的几个实现类是HashMap、LinkedHashMap、Hashtable和TreeMap。HashMap是Map接口的一个非同步的通用实现,Hashtable是HashMap的一个提供同步功能的副本(功能上这样讲,但内部实现不是基于ArrayList实现)。HashMap和Hashtable都不能像LinkedHashMap那样做任何排序保证。类似于TreeSet,TreeMap也是一个有序的数据结构,它按照键的值进行升序排列。
Java里什么时候使用List、Set和Map?
- 如果经常会使用索引来对容器中的元素进行访问,那么List是你的正确的选择。如果你已经知道索引了的话,那么List的实现类比如ArrayList可以提供更快速的访问。
- 如果你想容器中的元素能够按照它们插入的次序进行有序存储,那么还是 List,因为 List 是一个有序容器,它按照插入顺序进行存储。
- 如果你想保证插入元素的唯一性,也就是你不想有重复值的出现,那么可以选择一个 Set 的实现类,比如 HashSet、LinkedHashSet 或者 TreeSet。所有 Set 的实现类都遵循了统一约束比如唯一性,而且还提供了额外的特性比如 TreeSet 还是一个 SortedSet,所有存储于 TreeSet 中的元素可以使用 Java 里的 Comparator 或者 Comparable 进行排序。LinkedHashSet 也按照元素的插入顺序对它们进行存储。
- 如果你以键和值的形式进行数据存储那么 Map 是你正确的选择。你可以根据你的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。