Set集合與List一樣,都是繼承自Collection接口,常用的實現類有HashSet和TreeSet。值得注意的是,HashSet是通過HashMap來實現的而TreeSet是通過TreeMap來實現的,所以HashSet和TreeSet都沒有自己的數據結構,具體可以歸納如下:
•Set集合中的元素不能重復,即元素唯一
•HashSet按元素的哈希值存儲,所以是無序的,并且最多允許一個null對象
•TreeSet按元素的大小存儲,所以是有序的,并且不允許null對象
•Set集合沒有get方法,所以只能通過迭代器(Iterator)來遍歷元素,不能隨機訪問
1.HashSet
下面給出HashSet的部分源碼,以理解它的實現方式。
1
2
3
4
5
6
|
static final long serialVersionUID = -5024744406713321676L; private transient HashMap< E ,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); |
觀察源碼,我們知道HashSet的數據是存儲在HashMap的實例對象map中的,并且對應于map中的key,而Object類型的引用PRESENT則是對應于map中的value的一個虛擬值,沒有實際意義。聯想到HashMap的一些特性:無序存儲、key值唯一等等,我們就可以很自然地理解Set集合元素不能重復以及HashSet無序存儲的特性了。
下面從源代碼的角度來理解HashSet的基本用法:
•構造器(四種)
1.HashSet() 空的構造器,初始化一個空的HashMap
2.HashSet(Collection<? extends E> c) 傳入一個子集c,用于初始化HashMap
3.HashSet(int initialCapacity, float loadFactor) 初始化一個空的HashMap,并指定初始容量和加載因子
4.HashSet(int initialCapacity) 初始化一個空的HashMap,并指定初始容量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public HashSet() { map = new HashMap<>(); } public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); } public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); } |
•插入元素
1.add(E e) 插入指定元素(調用HashMap的put方法實現)
1
2
3
4
5
|
Set< String > hashSet = new HashSet< String >(); hashSet.add("D"); hashSet.add("B"); hashSet.add("C"); hashSet.add("A"); |
•查找元素
1.contains(Object o) 判斷集合中是否包含指定的元素(調用HashMap的containsKey方法實現)
1
2
3
|
public boolean contains(Object o) { return map.containsKey(o); } |
2.由于HashSet的實現類中沒有get方法,所以只能通過迭代器依次遍歷,而不能隨機訪問(調用HashMap中keySet的迭代器實現)
1
2
3
|
public Iterator< E > iterator() { return map.keySet().iterator(); } |
應用示例:
1
2
3
4
5
6
7
8
9
|
Set< String > hashSet = new HashSet< String >(); hashSet.add("D"); hashSet.add("B"); hashSet.add("C"); hashSet.add("A"); for (Iterator iterator = hashSet.iterator(); iterator.hasNext();) { String string = (String) iterator.next(); System.out.print(string+" "); }//D A B C |
•修改元素
由于HashMap中的key值不能修改,所以HashSet不能進行修改元素的操作
•刪除元素
1.remove(Object o) 刪除指定元素(調用HashMap中的remove方法實現,返回值為true或者false)
1
2
3
|
public boolean remove(Object o) { return map.remove(o)==PRESENT; } |
2.clear() 清空元素(調用HashMap中的clear方法實現,沒有返回值)
1
2
3
|
public void clear() { map.clear(); } |
2.TreeSet
TreeSet是SortedSet接口的唯一實現類。前面說過,TreeSet沒有自己的數據結構而是通過TreeMap實現的,所以TreeSet也是基于紅黑二叉樹的一種存儲結構,所以TreeSet不允許null對象,并且是有序存儲的(默認升序)。
1
2
3
4
|
private transient NavigableMap< E ,Object> m; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); |
上述源代碼中的NavigableMap是繼承自SrotedMap的一個接口,其實現類為TreeMap,因此TreeSet中的數據是通過TreeMap來存儲的,此處的PRESENT也是沒有實際意義的虛擬值。
下面從源代碼的角度來理解HashSet的基本用法:
•構造器(四種)
1.TreeSet() 空的構造器,初始化一個空的TreeMap,默認升序排列
2.TreeSet(Comparator<? super E> comparator) 傳入一個自定義的比較器,常常用于實現降序排列
3.TreeSet(Collection<? extends E> c) 傳入一個子集c,用于初始化TreeMap對象,默認升序
4.TreeSet(SortedSet<E> s) 傳入一個有序的子集s,用于初始化TreeMap對象,采用子集的比較器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public TreeSet() { this(new TreeMap< E ,Object>()); } public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); } public TreeSet(Collection<? extends E> c) { this(); addAll(c); } public TreeSet(SortedSet< E > s) { this(s.comparator()); addAll(s); } |
應用示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//自定義一個比較器,實現降序排列 Set< Integer > treeSet = new TreeSet< Integer >(new Comparator< Integer >() { @Override public int compare(Integer o1, Integer o2) { // return 0; //默認升序 return o2.compareTo(o1);//降序 } }); treeSet.add(200); treeSet.add(120); treeSet.add(150); treeSet.add(110); for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); } //200 150 120 110 |
1
2
3
4
5
6
7
8
9
10
11
12
13
|
ArrayList< Integer > list = new ArrayList< Integer >(); list.add(300); list.add(120); list.add(100); list.add(150); System.out.println(list); //[300, 120, 100, 150] //傳入一個子集,默認升序排列 TreeSet< Integer > treeSet = new TreeSet< Integer >(list); for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); }//100 120 150 300 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
/* * 傳入一個有序的子集,采用子集的比較器 * 注意子集的類型必須是SortedSet及其子類或者實現類,否則將采用默認的比較器 * 所以此處subSet的類型也可以是TreeSet。 */ SortedSet< Integer > subSet = new TreeSet< Integer >(new Comparator< Integer >() { @Override public int compare(Integer o1, Integer o2) { // return 0; //默認升序 return o2.compareTo(o1);//降序 } }); subSet.add(200); subSet.add(120); subSet.add(150); subSet.add(110); for (Iterator iterator = subSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); } //200 150 120 110 System.out.println(); Set< Integer > treeSet = new TreeSet< Integer >(subSet); for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); }//200 150 120 110 System.out.println(); treeSet.add(500); treeSet.add(100); treeSet.add(105); for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); }//500 200 150 120 110 105 100 |
• 插入元素
1.add(E e) 插入指定的元素(調用TreeMap的put方法實現)
2.addAll(Collection<? extends E> c) 插入一個子集c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
ArrayList< Integer > list = new ArrayList< Integer >(); list.add(300); list.add(120); list.add(100); list.add(150); System.out.println(list); //[300, 120, 100, 150] Set< Integer > treeSet = new TreeSet< Integer >(); //插入一個子集,默認升序 treeSet.addAll(list); for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); }//100 120 150 300 |
•查找元素
1.contains(Object o) 判斷集合中是否包含指定對象(調用TreeMap的containsKey方法實現)
2.與HashSet一樣,TreeSet的實現類中沒有get方法,所以只能通過迭代器依次遍歷,而不能隨機訪問(調用TreeMap中keySet的迭代器實現)。
•修改元素
TreeSet不能進行修改元素的操作,原因與HashSet一樣。
•刪除元素
1.remove(Object o) 刪除指定元素(調用TreeMap中的remove方法實現,返回true或者false)
1
2
3
|
public boolean remove(Object o) { return m.remove(o)==PRESENT; } |
2.clear() 清空元素(調用TreeMap中的clear方法實現,無返回值)
1
2
3
|
public void clear() { m.clear(); } |
應用示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
ArrayList< Integer > list = new ArrayList< Integer >(); list.add(300); list.add(120); list.add(100); list.add(150); System.out.println(list); //[300, 120, 100, 150] Set< Integer > treeSet = new TreeSet< Integer >(); //插入一個子集,默認升序 treeSet.addAll(list); for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); }//100 120 150 300 System.out.println(treeSet.remove(100));//true for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) { Integer integer = (Integer) iterator.next(); System.out.print(integer+" "); }//120 150 300 treeSet.clear(); System.out.println(treeSet.size());//0 |
至此,HashSet和TreeSet的存儲結構及基本用法介紹完畢。
以上這篇java集合類源碼分析之Set詳解就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/Wilange/p/7638646.html