Java基础知识_Set集合

一、HashSet剖析

按照国际惯例,我们来看看HashSet的顶部注释

 1 /**
 2  * This class implements the <tt>Set</tt> interface, backed by a hash table
 3  * (actually a <tt>HashMap</tt> instance).  It makes no guarantees as to the
 4  * iteration order of the set; in particular, it does not guarantee that the
 5  * order will remain constant over time.  This class permits the <tt>null</tt>
 6  * element.
 7  *
 8  * <p>This class offers constant time performance for the basic operations
 9  * (<tt>add</tt>, <tt>remove</tt>, <tt>contains</tt> and <tt>size</tt>),
10  * assuming the hash function disperses the elements properly among the
11  * buckets.  Iterating over this set requires time proportional to the sum of
12  * the <tt>HashSet</tt> instance's size (the number of elements) plus the
13  * "capacity" of the backing <tt>HashMap</tt> instance (the number of
14  * buckets).  Thus, it's very important not to set the initial capacity too
15  * high (or the load factor too low) if iteration performance is important.
16  *
17  * <p><strong>Note that this implementation is not synchronized.</strong>
18  * If multiple threads access a hash set concurrently, and at least one of
19  * the threads modifies the set, it <i>must</i> be synchronized externally.
20  * This is typically accomplished by synchronizing on some object that
21  * naturally encapsulates the set.
22  *
23  * If no such object exists, the set should be "wrapped" using the
24  * {@link Collections#synchronizedSet Collections.synchronizedSet}
25  * method.  This is best done at creation time, to prevent accidental
26  * unsynchronized access to the set:<pre>
27  *   Set s = Collections.synchronizedSet(new HashSet(...));</pre>
28  *
29  * <p>The iterators returned by this class's <tt>iterator</tt> method are
30  * <i>fail-fast</i>: if the set is modified at any time after the iterator is
31  * created, in any way except through the iterator's own <tt>remove</tt>
32  * method, the Iterator throws a {@link ConcurrentModificationException}.
33  * Thus, in the face of concurrent modification, the iterator fails quickly
34  * and cleanly, rather than risking arbitrary, non-deterministic behavior at
35  * an undetermined time in the future.
36  *
37  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
38  * as it is, generally speaking, impossible to make any hard guarantees in the
39  * presence of unsynchronized concurrent modification.  Fail-fast iterators
40  * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
41  * Therefore, it would be wrong to write a program that depended on this
42  * exception for its correctness: <i>the fail-fast behavior of iterators
43  * should be used only to detect bugs.</i>
44  *
45  * <p>This class is a member of the
46  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
47  * Java Collections Framework</a>.
48  *
49  * @param <E> the type of elements maintained by this set
50  *
51  * @author  Josh Bloch
52  * @author  Neal Gafter
53  * @see     Collection
54  * @see     Set
55  * @see     TreeSet
56  * @see     HashMap
57  * @since   1.2
58  */

从顶部注释来看我们可以归纳HashSet的要点了

  实现Set接口

  不保证迭代顺序

  允许元素为null

  底层实际上是一个HashMap实例

  非同步

  初始容量非常影响迭代性能

1     public HashSet() {
2         map = new HashMap<>();
3     }

我们知道Map是一个映射,有value有key的,既然HashSet底层用的是HashMap,那么value在哪里呢???

1  // Dummy value to associate with an Object in the backing Map
2     private static final Object PRESENT = new Object();

value是一个Object,所有的value都是它

所以可以直接总结出:HashSet实际上就是封装了HashMap,操作HashSet元素实际上就是操作HashMap。也是面向对象的一种体现,重用性贼高。

 

二、TreeSet剖析

按照惯例,我们来看看TreeSet顶部注释

 1 /**
 2  * A {@link NavigableSet} implementation based on a {@link TreeMap}.
 3  * The elements are ordered using their {@linkplain Comparable natural
 4  * ordering}, or by a {@link Comparator} provided at set creation
 5  * time, depending on which constructor is used.
 6  *
 7  * <p>This implementation provides guaranteed log(n) time cost for the basic
 8  * operations ({@code add}, {@code remove} and {@code contains}).
 9  *
10  * <p>Note that the ordering maintained by a set (whether or not an explicit
11  * comparator is provided) must be <i>consistent with equals</i> if it is to
12  * correctly implement the {@code Set} interface.  (See {@code Comparable}
13  * or {@code Comparator} for a precise definition of <i>consistent with
14  * equals</i>.)  This is so because the {@code Set} interface is defined in
15  * terms of the {@code equals} operation, but a {@code TreeSet} instance
16  * performs all element comparisons using its {@code compareTo} (or
17  * {@code compare}) method, so two elements that are deemed equal by this method
18  * are, from the standpoint of the set, equal.  The behavior of a set
19  * <i>is</i> well-defined even if its ordering is inconsistent with equals; it
20  * just fails to obey the general contract of the {@code Set} interface.
21  *
22  * <p><strong>Note that this implementation is not synchronized.</strong>
23  * If multiple threads access a tree set concurrently, and at least one
24  * of the threads modifies the set, it <i>must</i> be synchronized
25  * externally.  This is typically accomplished by synchronizing on some
26  * object that naturally encapsulates the set.
27  * If no such object exists, the set should be "wrapped" using the
28  * {@link Collections#synchronizedSortedSet Collections.synchronizedSortedSet}
29  * method.  This is best done at creation time, to prevent accidental
30  * unsynchronized access to the set: <pre>
31  *   SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));</pre>
32  *
33  * <p>The iterators returned by this class's {@code iterator} method are
34  * <i>fail-fast</i>: if the set is modified at any time after the iterator is
35  * created, in any way except through the iterator's own {@code remove}
36  * method, the iterator will throw a {@link ConcurrentModificationException}.
37  * Thus, in the face of concurrent modification, the iterator fails quickly
38  * and cleanly, rather than risking arbitrary, non-deterministic behavior at
39  * an undetermined time in the future.
40  *
41  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
42  * as it is, generally speaking, impossible to make any hard guarantees in the
43  * presence of unsynchronized concurrent modification.  Fail-fast iterators
44  * throw {@code ConcurrentModificationException} on a best-effort basis.
45  * Therefore, it would be wrong to write a program that depended on this
46  * exception for its correctness:   <i>the fail-fast behavior of iterators
47  * should be used only to detect bugs.</i>
48  *
49  * <p>This class is a member of the
50  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
51  * Java Collections Framework</a>.
52  *
53  * @param <E> the type of elements maintained by this set
54  *
55  * @author  Josh Bloch
56  * @see     Collection
57  * @see     Set
58  * @see     HashSet
59  * @see     Comparable
60  * @see     Comparator
61  * @see     TreeMap
62  * @since   1.2
63  */

底层是Treemap,实现了NavigableSet接口,根据Comparable在实现自然排序,或者在创建对象时,使用构造方法传递Comparator对象实现排序,时间复杂度是logn,通过compareTo或者compare方法认证元素是否相等。非同步

我们来归纳一下TreeSet

  实现NavigableSet接口

  可以实现排序功能

  底层实际上是一个TreeMap实例

  非同步

 1 private static final Object PRESENT = new Object();
 2 
 3     /**
 4      * Constructs a set backed by the specified navigable map.
 5      */
 6     TreeSet(NavigableMap<E,Object> m) {
 7         this.m = m;
 8     }
 9 
10     /**
11      * Constructs a new, empty tree set, sorted according to the
12      * natural ordering of its elements.  All elements inserted into
13      * the set must implement the {@link Comparable} interface.
14      * Furthermore, all such elements must be <i>mutually
15      * comparable</i>: {@code e1.compareTo(e2)} must not throw a
16      * {@code ClassCastException} for any elements {@code e1} and
17      * {@code e2} in the set.  If the user attempts to add an element
18      * to the set that violates this constraint (for example, the user
19      * attempts to add a string element to a set whose elements are
20      * integers), the {@code add} call will throw a
21      * {@code ClassCastException}.
22      */
23     public TreeSet() {
24         this(new TreeMap<E,Object>());
25     }

Map的value是new Object();

实例是new TreeMap<E,Object>()

 

三、LinkedHashSet剖析

按照国际惯例,看看LinkedHashSet顶部注释:

 1 /**
 2  * <p>Hash table and linked list implementation of the <tt>Set</tt> interface,
 3  * with predictable iteration order.  This implementation differs from
 4  * <tt>HashSet</tt> in that it maintains a doubly-linked list running through
 5  * all of its entries.  This linked list defines the iteration ordering,
 6  * which is the order in which elements were inserted into the set
 7  * (<i>insertion-order</i>).  Note that insertion order is <i>not</i> affected
 8  * if an element is <i>re-inserted</i> into the set.  (An element <tt>e</tt>
 9  * is reinserted into a set <tt>s</tt> if <tt>s.add(e)</tt> is invoked when
10  * <tt>s.contains(e)</tt> would return <tt>true</tt> immediately prior to
11  * the invocation.)
12  *
13  * <p>This implementation spares its clients from the unspecified, generally
14  * chaotic ordering provided by {@link HashSet}, without incurring the
15  * increased cost associated with {@link TreeSet}.  It can be used to
16  * produce a copy of a set that has the same order as the original, regardless
17  * of the original set's implementation:
18  * <pre>
19  *     void foo(Set s) {
20  *         Set copy = new LinkedHashSet(s);
21  *         ...
22  *     }
23  * </pre>
24  * This technique is particularly useful if a module takes a set on input,
25  * copies it, and later returns results whose order is determined by that of
26  * the copy.  (Clients generally appreciate having things returned in the same
27  * order they were presented.)
28  *
29  * <p>This class provides all of the optional <tt>Set</tt> operations, and
30  * permits null elements.  Like <tt>HashSet</tt>, it provides constant-time
31  * performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
32  * <tt>remove</tt>), assuming the hash function disperses elements
33  * properly among the buckets.  Performance is likely to be just slightly
34  * below that of <tt>HashSet</tt>, due to the added expense of maintaining the
35  * linked list, with one exception: Iteration over a <tt>LinkedHashSet</tt>
36  * requires time proportional to the <i>size</i> of the set, regardless of
37  * its capacity.  Iteration over a <tt>HashSet</tt> is likely to be more
38  * expensive, requiring time proportional to its <i>capacity</i>.
39  *
40  * <p>A linked hash set has two parameters that affect its performance:
41  * <i>initial capacity</i> and <i>load factor</i>.  They are defined precisely
42  * as for <tt>HashSet</tt>.  Note, however, that the penalty for choosing an
43  * excessively high value for initial capacity is less severe for this class
44  * than for <tt>HashSet</tt>, as iteration times for this class are unaffected
45  * by capacity.
46  *
47  * <p><strong>Note that this implementation is not synchronized.</strong>
48  * If multiple threads access a linked hash set concurrently, and at least
49  * one of the threads modifies the set, it <em>must</em> be synchronized
50  * externally.  This is typically accomplished by synchronizing on some
51  * object that naturally encapsulates the set.
52  *
53  * If no such object exists, the set should be "wrapped" using the
54  * {@link Collections#synchronizedSet Collections.synchronizedSet}
55  * method.  This is best done at creation time, to prevent accidental
56  * unsynchronized access to the set: <pre>
57  *   Set s = Collections.synchronizedSet(new LinkedHashSet(...));</pre>
58  *
59  * <p>The iterators returned by this class's <tt>iterator</tt> method are
60  * <em>fail-fast</em>: if the set is modified at any time after the iterator
61  * is created, in any way except through the iterator's own <tt>remove</tt>
62  * method, the iterator will throw a {@link ConcurrentModificationException}.
63  * Thus, in the face of concurrent modification, the iterator fails quickly
64  * and cleanly, rather than risking arbitrary, non-deterministic behavior at
65  * an undetermined time in the future.
66  *
67  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
68  * as it is, generally speaking, impossible to make any hard guarantees in the
69  * presence of unsynchronized concurrent modification.  Fail-fast iterators
70  * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
71  * Therefore, it would be wrong to write a program that depended on this
72  * exception for its correctness:   <i>the fail-fast behavior of iterators
73  * should be used only to detect bugs.</i>
74  *
75  * <p>This class is a member of the
76  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
77  * Java Collections Framework</a>.
78  *
79  * @param <E> the type of elements maintained by this set
80  *
81  * @author  Josh Bloch
82  * @see     Object#hashCode()
83  * @see     Collection
84  * @see     Set
85  * @see     HashSet
86  * @see     TreeSet
87  * @see     Hashtable
88  * @since   1.4
89  */

迭代有序,维护了一个双项链表,允许为null,性能比HashSet差一点点,因为要维护双向链表,迭代的是双向链表。非同步的。

从顶部注释来看,我们可以归纳LinkedHashSet的要点

  迭代是有序的

  允许为null

  底层实际上是一个HashMap+双向链表的实例(其实就是LinkedHashMap)

  非同步

  性能比HashSet差一丢丢,因为要维护一个双向链表。

  初始容量与迭代无关,LinkedHashSet迭代的是双向链表

 

四、总结

可以明显的看到,Set集合的底层就是Map,所以没有做什么分析,也没什么好分析的

下面稍微总结一下吧

HashSet 

  无序,允许为null,底层是HashMap(散列表+红黑树),非线程同步

TreeSet

  迭代有序,不允许为null,底层是TreeMap(红黑树),非线程同步

LinkedHashSet:

  迭代有序,允许为null,底层是HashMap+双向链表,非线程同步

posted @ 2019-09-10 15:34  chyblogs  阅读(219)  评论(0)    收藏  举报