Java 深入学习(1) —— 容器类(集合类)Set、List、Queue、Map 之间的区别

容器类大致分类示意图


(非精确分类)(绿色表示 interface,蓝色表示 class)

这里写图片描述

这里写图片描述


容器类类库划分


1、 Collection。一个独立元素的序列。这些元素都服从一条或多条规则。

List 必须按照插入顺序保存元素
Set 不能有重复元素
Queue 按照排队规则来确定对象产生的顺序

所有 Collection 都可以使用 foreach 遍历
Collection 在每个“槽”中只能保存一个元素

Collection 常用方法:

boolean add(E e)
Ensures that this collection contains the specified element (optional operation).

boolean addAll(Collection<? extends E> c)
Adds all of the elements in the specified collection to this collection (optional operation).

void    clear()
Removes all of the elements from this collection (optional operation).

boolean contains(Object o)
Returns true if this collection contains the specified element.

boolean containsAll(Collection<?> c)
Returns true if this collection contains all of the elements in the specified collection.

boolean equals(Object o)
Compares the specified object with this collection for equality.

int hashCode()
Returns the hash code value for this collection.

boolean isEmpty()
Returns true if this collection contains no elements.

Iterator<E> iterator()
Returns an iterator over the elements in this collection.

boolean remove(Object o)
Removes a single instance of the specified element from this collection, if it is present (optional operation).

int size()
Returns the number of elements in this collection.

2、Map。一组成对的“键值对”对象,允许使用 key 来查找 value。

HashMap 提供了最快的查找技术,但没有按照任何明显的顺序来保存其元素
TreeMap 按照比较结果的升序保存键
LinkedHashMap 按照插入顺序保存键,同时保留了 HashMap 的查询速度

Map在每个“槽”中保存了两个对象

Map 常用方法:

boolean containsKey(Object key)
Returns true if this map contains a mapping for the specified key.

boolean containsValue(Object value)
Returns true if this map maps one or more keys to the specified 
value.

Set<Map.Entry<K,V>> entrySet()
Returns a Set view of the mappings contained in this map.

boolean equals(Object o)
Compares the specified object with this map for equality.

V   get(Object key)
Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.

default V   getOrDefault(Object key, V defaultValue)
Returns the value to which the specified key is mapped, or defaultValue if this map contains no mapping for the key.

int hashCode()
Returns the hash code value for this map.

boolean isEmpty()
Returns true if this map contains no key-value mappings.

Set<K>  keySet()
Returns a Set view of the keys contained in this map.

V   put(K key, V value)
Associates the specified value with the specified key in this map (optional operation).

V   remove(Object key)
Removes the mapping for a key from this map if it is present (optional operation).

int size()
Returns the number of key-value mappings in this map.

Collection<V>   values()
Returns a Collection view of the values contained in this map.

List


List 承诺可以将元素维护在特定的序列中。

ArrayList 优点是随机访问元素速度快,但在 List 中插入和删除元素时较慢
LinkedList 在List 中间插入和删除代价较低,提供了优化的顺序访问。但随机访问较慢

Arrays.asList() 方法接受一个数组或是一个用逗号分隔的元素列表(使用可变参数),并将其转换为一个 List 对象。

ArrayList


List 接口的可调整大小的实现。实现所有可选的 List 操作,并允许所有元素,包括null。除了实现List接口之外,该类还提供了一些方法来处理内部用来存储列表的数组的大小。 (这个类大致相当于Vector,除了它是不同步的。)

The size, isEmpty, get, set, iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time, that is, adding n elements requires O(n) time.All of the other operations run in linear time (roughly speaking). 

add() 操作的时间复杂度为 O(n),size, isEmpty, get, set, iterator, and listIterator 操作的时间复杂度为O(1)。

Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be "wrapped" using the Collections.synchronizedList method. This is best done at creation time, to prevent accidental unsynchronized access to the list:

List list = Collections.synchronizedList(new ArrayList(...));

请注意,此实现不同步。如果多个线程同时访问 ArrayList 实例,并且至少有一个线程在结构上修改了列表,则它必须在外部进行同步。 (结构修改是添加或删除一个或多个元素,或明确调整后备数组的大小的任何操作;仅仅设置元素的值不是一个结构修改。)


LinkedList


Doubly-linked list implementation of the List and Deque interfaces. Implements all optional list operations, and permits all elements (including null).
All of the operations perform as could be expected for a doubly-linked list. Operations that index into the list will traverse the list from the beginning or the end, whichever is closer to the specified index.

LinkedList 实现了 List 和 Deque 接口。实现所有可选的 List 操作,并允许所有元素(包括null)

Note that this implementation is not synchronized.

注意这个实现不是同步的。

List list = Collections.synchronizedList(new LinkedList(...));

Set

Set 不保存重复的元素,基于对象的值来确定归属性。

HashSet 使用的是散列函数
TreeSet 将元素存储在红黑树中
LinkedHashSet 因为查询速度使用了散列,看起来使用了链表来维护元素的插入顺序

HashSet


这个类实现了Set接口,由一个HashTable(实际上是一个HashMap实例)支持。对 Set 的迭代次序没有保证,特别是不能保证次序会随着时间的推移而保持不变。这个类允许null元素。

这个类为基本操作(add, remove, contains and size)提供了恒定的时间性能,假设散列函数在桶之间正确地分散元素。遍历这个集合需要的时间与HashSet实例的大小(元素数量)加上支持HashMap实例的“容量”(桶的数量)的总和成正比。因此,如果迭代性能很重要,不要将初始容量设置得太高(或者负载因子太低)。

请注意,此实现不同步。如果多个线程同时访问哈希集合,并且至少有一个线程修改了集合,则它必须在外部进行同步。

Set s = Collections.synchronizedSet(new HashSet(...));

TreeSet


基于TreeMap的NavigableSet实现。这些元素是按照自然顺序排序的,或者是在创建集合时提供的比较器,具体取决于使用哪个构造函数。

这个实现为基本操作(add, remove and contains)时间复杂度为 log(n)

请注意,此实现不同步。如果多个线程同时访问一个树集,并且至少有一个线程修改了这个集,那么它必须在外部进行同步。这通常是通过同步一些自然封装集合的对象来实现的。如果不存在这样的对象,则应该使用Collections.synchronizedSortedSet方法来“包装”该集合。这最好在创建时完成,以防止意外的不同步访问集合:

SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));

Queue


队列是一个典型的先进先出(FIFO)的容器。即从容器的一段放入事物,从另一端取出,并且事物放入容器的顺序与取出的顺序是相同的。


PriorityQueue


基于 priority heap 的 unbounded priority queue。优先级队列的元素根据其自然顺序进行排序,或者由队列构建时提供的比较器进行排序,具体取决于使用哪个构造函数。优先级队列不允许空元素。依赖于自然顺序的优先级队列也不允许插入不可比较的对象(这样做可能导致ClassCastException)。

这个队列的头是相对于指定顺序的最小元素。

请注意,此实现不同步。如果任何线程修改队列,则多个线程不应该同时访问PriorityQueue实例。而是使用线程安全的PriorityBlockingQueue类。

实现注意事项:
入队和出队方法(offer, poll, remove() and add)时间复杂度为 O(log(n)) 
remove(Object)contains(Object)  时间复杂度为 O(n)
检索方法 (peek, element, and size) 的时间复杂度为 O(1)

Map

Map 可以返回它的键的 Set, 它的值得 Collection, 或是它的键值对的 Set。


HashMap


这个实现提供了所有可选的 Map 操作,并且允许空值和null键。 (HashMap 大致等同于 Hashtable ,除了它是不同步的并且允许空值的。)

基本操作(get和put)提供了恒定的性能,假设散列函数在桶之间正确分散元素。

请注意,此实现不同步。

Map m = Collections.synchronizedMap(new HashMap(...));

TreeMap


基于红黑树的NavigableMap实现。该地图根据其按键的自然顺序或者在 Map 创建时提供的比较器进行排序,具体取决于使用哪个构造函数。

这个实现为containsKey,get,put和remove操作时间复杂度为 log(n)。

请注意,此实现不同步。

SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));

总结

  1. 如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。

  2. 如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。

  3. 在除需要排序时使用TreeSet,TreeMap外,都应使用HashSet,HashMap,因为他们 的效率更高。

  4. 要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。

  5. 容器类仅能持有对象引用(指向对象的指针),而不是将对象信息copy一份至数列某位置。一旦将对象置入容器内,便损失了该对象的型别信息。

  6. 尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。

  7. LinkedListArrayListHashSetTreeSetPriorityQueueHashMapTreeMapLinkedHashMap非线程安全的VectorHashTable线程安全的;


Reference

java中Map,List与Set的区别
http://blog.csdn.net/speedme/article/details/22398395

java 常用集合list与Set、Map区别及适用场景总结
http://blog.csdn.net/qq_22118507/article/details/51576319


Java API 文档

https://docs.oracle.com/javase/8/docs/api/java/util/Set.html

https://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html

https://docs.oracle.com/javase/8/docs/api/java/util/TreeSet.html

https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html

https://docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html

https://docs.oracle.com/javase/8/docs/api/java/util/Map.html

https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html

https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值