一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - TreeSet詳解和使用示例_動力節點Java學院整理

TreeSet詳解和使用示例_動力節點Java學院整理

2020-09-30 15:51skywang12345 Java教程

TreeSet 是一個有序的集合,它的作用是提供有序的Set集合。這篇文章主要介紹了TreeSet使用示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下

第1部分 TreeSet介紹

TreeSet簡介

TreeSet 是一個有序的集合,它的作用是提供有序的Set集合。它繼承于AbstractSet抽象類,實現了NavigableSet<E>, Cloneable, java.io.Serializable接口。
TreeSet 繼承于AbstractSet,所以它是一個Set集合,具有Set的屬性和方法。
TreeSet 實現了NavigableSet接口,意味著它支持一系列的導航方法。比如查找與指定目標最匹配項。
TreeSet 實現了Cloneable接口,意味著它能被克隆。
TreeSet 實現了java.io.Serializable接口,意味著它支持序列化。
TreeSet是基于TreeMap實現的。TreeSet中的元素支持2種排序方式:自然排序 或者 根據創建TreeSet 時提供的 Comparator 進行排序。這取決于使用的構造方法。
TreeSet為基本操作(add、remove 和 contains)提供受保證的 log(n) 時間開銷。
另外,TreeSet是非同步的。 它的iterator 方法返回的迭代器是fail-fast的。 

TreeSet的構造函數

?
1
2
3
4
5
6
7
8
9
10
11
// 默認構造函數。使用該構造函數,TreeSet中的元素按照自然排序進行排列。
TreeSet()
 
// 創建的TreeSet包含collection
TreeSet(Collection<? extends E> collection)
 
// 指定TreeSet的比較器
TreeSet(Comparator<? super E> comparator)
 
// 創建的TreeSet包含set
TreeSet(SortedSet<E> set)

TreeSet的API

?
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
boolean       add(E object)
boolean       addAll(Collection<? extends E> collection)
void           clear()
Object         clone()
boolean        contains(Object object)
E             first()
boolean        isEmpty()
E             last()
E             pollFirst()
E             pollLast()
E             lower(E e)
E             floor(E e)
E             ceiling(E e)
E             higher(E e)
boolean       remove(Object object)
int            size()
Comparator<? super E>   comparator()
Iterator<E>        iterator()
Iterator<E>        descendingIterator()
SortedSet<E>       headSet(E end)
NavigableSet<E>      descendingSet()
NavigableSet<E>      headSet(E end, boolean endInclusive)
SortedSet<E>       subSet(E start, E end)
NavigableSet<E>      subSet(E start, boolean startInclusive, E end, boolean endInclusive)
NavigableSet<E>      tailSet(E start, boolean startInclusive)
SortedSet<E>       tailSet(E start)

說明:

(01) TreeSet是有序的Set集合,因此支持add、remove、get等方法。
(02) 和NavigableSet一樣,TreeSet的導航方法大致可以區分為兩類,一類時提供元素項的導航方法,返回某個元素;另一類時提供集合的導航方法,返回某個集合。
lower、floor、ceiling 和 higher 分別返回小于、小于等于、大于等于、大于給定元素的元素,如果不存在這樣的元素,則返回 null。 

第2部分 TreeSet數據結構

TreeSet的繼承關系

?
1
2
3
4
5
6
7
java.lang.Object
  ?   java.util.AbstractCollection<E>
     ?   java.util.AbstractSet<E>
        ?   java.util.TreeSet<E>
 
public class TreeSet<E> extends AbstractSet<E>   
  implements NavigableSet<E>, Cloneable, java.io.Serializable{}

TreeSet與Collection關系如下圖:

TreeSet詳解和使用示例_動力節點Java學院整理

從圖中可以看出:
(01) TreeSet繼承于AbstractSet,并且實現了NavigableSet接口。
(02) TreeSet的本質是一個"有序的,并且沒有重復元素"的集合,它是通過TreeMap實現的。TreeSet中含有一個"NavigableMap類型的成員變量"m,而m實際上是"TreeMap的實例"。

第3部分 TreeSet源碼解析(基于JDK1.6.0_45)

為了更了解TreeSet的原理,下面對TreeSet源碼代碼作出分析。

 

?
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
package java.util;
 
public class TreeSet<E> extends AbstractSet<E>
  implements NavigableSet<E>, Cloneable, java.io.Serializable
{
  // NavigableMap對象
  private transient NavigableMap<E,Object> m;
 
  // TreeSet是通過TreeMap實現的,
  // PRESENT是鍵-值對中的值。
  private static final Object PRESENT = new Object();
 
  // 不帶參數的構造函數。創建一個空的TreeMap
  public TreeSet() {
    this(new TreeMap<E,Object>());
  }
 
  // 將TreeMap賦值給 "NavigableMap對象m"
  TreeSet(NavigableMap<E,Object> m) {
    this.m = m;
  }
 
  // 帶比較器的構造函數。
  public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<E,Object>(comparator));
  }
 
  // 創建TreeSet,并將集合c中的全部元素都添加到TreeSet中
  public TreeSet(Collection<? extends E> c) {
    this();
    // 將集合c中的元素全部添加到TreeSet中
    addAll(c);
  }
 
  // 創建TreeSet,并將s中的全部元素都添加到TreeSet中
  public TreeSet(SortedSet<E> s) {
    this(s.comparator());
    addAll(s);
  }
 
  // 返回TreeSet的順序排列的迭代器。
  // 因為TreeSet時TreeMap實現的,所以這里實際上時返回TreeMap的“鍵集”對應的迭代器
  public Iterator<E> iterator() {
    return m.navigableKeySet().iterator();
  }
 
  // 返回TreeSet的逆序排列的迭代器。
  // 因為TreeSet時TreeMap實現的,所以這里實際上時返回TreeMap的“鍵集”對應的迭代器
  public Iterator<E> descendingIterator() {
    return m.descendingKeySet().iterator();
  }
 
  // 返回TreeSet的大小
  public int size() {
    return m.size();
  }
 
  // 返回TreeSet是否為空
  public boolean isEmpty() {
    return m.isEmpty();
  }
 
  // 返回TreeSet是否包含對象(o)
  public boolean contains(Object o) {
    return m.containsKey(o);
  }
 
  // 添加e到TreeSet中
  public boolean add(E e) {
    return m.put(e, PRESENT)==null;
  }
 
  // 刪除TreeSet中的對象o
  public boolean remove(Object o) {
    return m.remove(o)==PRESENT;
  }
 
  // 清空TreeSet
  public void clear() {
    m.clear();
  }
 
  // 將集合c中的全部元素添加到TreeSet中
  public boolean addAll(Collection<? extends E> c) {
    // Use linear-time version if applicable
    if (m.size()==0 && c.size() > 0 &&
      c instanceof SortedSet &&
      m instanceof TreeMap) {
      SortedSet<? extends E> set = (SortedSet<? extends E>) c;
      TreeMap<E,Object> map = (TreeMap<E, Object>) m;
      Comparator<? super E> cc = (Comparator<? super E>) set.comparator();
      Comparator<? super E> mc = map.comparator();
      if (cc==mc || (cc != null && cc.equals(mc))) {
        map.addAllForTreeSet(set, PRESENT);
        return true;
      }
    }
    return super.addAll(c);
  }
 
  // 返回子Set,實際上是通過TreeMap的subMap()實現的。
  public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
                 E toElement,  boolean toInclusive) {
    return new TreeSet<E>(m.subMap(fromElement, fromInclusive,
                    toElement,  toInclusive));
  }
 
  // 返回Set的頭部,范圍是:從頭部到toElement。
  // inclusive是是否包含toElement的標志
  public NavigableSet<E> headSet(E toElement, boolean inclusive) {
    return new TreeSet<E>(m.headMap(toElement, inclusive));
  }
 
  // 返回Set的尾部,范圍是:從fromElement到結尾。
  // inclusive是是否包含fromElement的標志
  public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
    return new TreeSet<E>(m.tailMap(fromElement, inclusive));
  }
 
  // 返回子Set。范圍是:從fromElement(包括)到toElement(不包括)。
  public SortedSet<E> subSet(E fromElement, E toElement) {
    return subSet(fromElement, true, toElement, false);
  }
 
  // 返回Set的頭部,范圍是:從頭部到toElement(不包括)。
  public SortedSet<E> headSet(E toElement) {
    return headSet(toElement, false);
  }
 
  // 返回Set的尾部,范圍是:從fromElement到結尾(不包括)。
  public SortedSet<E> tailSet(E fromElement) {
    return tailSet(fromElement, true);
  }
 
  // 返回Set的比較器
  public Comparator<? super E> comparator() {
    return m.comparator();
  }
 
  // 返回Set的第一個元素
  public E first() {
    return m.firstKey();
  }
 
  // 返回Set的最后一個元素
  public E first() {
  public E last() {
    return m.lastKey();
  }
 
  // 返回Set中小于e的最大元素
  public E lower(E e) {
    return m.lowerKey(e);
  }
 
  // 返回Set中小于/等于e的最大元素
  public E floor(E e) {
    return m.floorKey(e);
  }
 
  // 返回Set中大于/等于e的最小元素
  public E ceiling(E e) {
    return m.ceilingKey(e);
  }
 
  // 返回Set中大于e的最小元素
  public E higher(E e) {
    return m.higherKey(e);
  }
 
  // 獲取第一個元素,并將該元素從TreeMap中刪除。
  public E pollFirst() {
    Map.Entry<E,?> e = m.pollFirstEntry();
    return (e == null)? null : e.getKey();
  }
 
  // 獲取最后一個元素,并將該元素從TreeMap中刪除。
  public E pollLast() {
    Map.Entry<E,?> e = m.pollLastEntry();
    return (e == null)? null : e.getKey();
  }
 
  // 克隆一個TreeSet,并返回Object對象
  public Object clone() {
    TreeSet<E> clone = null;
    try {
      clone = (TreeSet<E>) super.clone();
    } catch (CloneNotSupportedException e) {
      throw new InternalError();
    }
 
    clone.m = new TreeMap<E,Object>(m);
    return clone;
  }
 
  // java.io.Serializable的寫入函數
  // 將TreeSet的“比較器、容量,所有的元素值”都寫入到輸出流中
  private void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException {
    s.defaultWriteObject();
 
    // 寫入比較器
    s.writeObject(m.comparator());
 
    // 寫入容量
    s.writeInt(m.size());
 
    // 寫入“TreeSet中的每一個元素”
    for (Iterator i=m.keySet().iterator(); i.hasNext(); )
      s.writeObject(i.next());
  }
 
  // java.io.Serializable的讀取函數:根據寫入方式讀出
  // 先將TreeSet的“比較器、容量、所有的元素值”依次讀出
  private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
    // Read in any hidden stuff
    s.defaultReadObject();
 
    // 從輸入流中讀取TreeSet的“比較器”
    Comparator<? super E> c = (Comparator<? super E>) s.readObject();
 
    TreeMap<E,Object> tm;
    if (c==null)
      tm = new TreeMap<E,Object>();
    else
      tm = new TreeMap<E,Object>(c);
    m = tm;
 
    // 從輸入流中讀取TreeSet的“容量”
    int size = s.readInt();
 
    // 從輸入流中讀取TreeSet的“全部元素”
    tm.readTreeSet(size, s, PRESENT);
  }
 
  // TreeSet的序列版本號
  private static final long serialVersionUID = -2479143000061671589L;
}

總結:

(01) TreeSet實際上是TreeMap實現的。當我們構造TreeSet時;若使用不帶參數的構造函數,則TreeSet的使用自然比較器;若用戶需要使用自定義的比較器,則需要使用帶比較器的參數。
(02) TreeSet是非線程安全的。
(03) TreeSet實現java.io.Serializable的方式。當寫入到輸出流時,依次寫入“比較器、容量、全部元素”;當讀出輸入流時,再依次讀取。 

第4部分 TreeSet遍歷方式

4.1 Iterator順序遍歷

?
1
2
3
for(Iterator iter = set.iterator(); iter.hasNext(); ) {
  iter.next();

4.2 Iterator順序遍歷

?
1
2
3
4
// 假設set是TreeSet對象
for(Iterator iter = set.descendingIterator(); iter.hasNext(); ) {
  iter.next();
}

4.3 for-each遍歷HashSet

?
1
2
3
4
// 假設set是TreeSet對象,并且set中元素是String類型
String[] arr = (String[])set.toArray(new String[0]);
for (String str:arr)
  System.out.printf("for each : %s\n", str);

TreeSet不支持快速隨機遍歷,只能通過迭代器進行遍歷! 

TreeSet遍歷測試程序如下:

?
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
39
40
41
42
43
44
45
46
47
48
49
50
import java.util.*;
 
/**
 * @desc TreeSet的遍歷程序
 *
 * @author skywang
 * @email [email protected]
 */
public class TreeSetIteratorTest {
 
  public static void main(String[] args) {
    TreeSet set = new TreeSet();
    set.add("aaa");
    set.add("aaa");
    set.add("bbb");
    set.add("eee");
    set.add("ddd");
    set.add("ccc");
 
    // 順序遍歷TreeSet
    ascIteratorThroughIterator(set) ;
    // 逆序遍歷TreeSet
    descIteratorThroughIterator(set);
    // 通過for-each遍歷TreeSet。不推薦!此方法需要先將Set轉換為數組
    foreachTreeSet(set);
  }
 
  // 順序遍歷TreeSet
  public static void ascIteratorThroughIterator(TreeSet set) {
    System.out.print("\n ---- Ascend Iterator ----\n");
    for(Iterator iter = set.iterator(); iter.hasNext(); ) {
      System.out.printf("asc : %s\n", iter.next());
    }
  }
 
  // 逆序遍歷TreeSet
  public static void descIteratorThroughIterator(TreeSet set) {
    System.out.printf("\n ---- Descend Iterator ----\n");
    for(Iterator iter = set.descendingIterator(); iter.hasNext(); )
      System.out.printf("desc : %s\n", (String)iter.next());
  }
 
  // 通過for-each遍歷TreeSet。不推薦!此方法需要先將Set轉換為數組
  private static void foreachTreeSet(TreeSet set) {
    System.out.printf("\n ---- For-each ----\n");
    String[] arr = (String[])set.toArray(new String[0]);
    for (String str:arr)
      System.out.printf("for each : %s\n", str);
  }
}

運行結果:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---- Ascend Iterator ----
asc : aaa
asc : bbb
asc : ccc
asc : ddd
asc : eee
 
 ---- Descend Iterator ----
desc : eee
desc : ddd
desc : ccc
desc : bbb
desc : aaa
 
 ---- For-each ----
for each : aaa
for each : bbb
for each : ccc
for each : ddd
for each : eee

 

 第5部分 TreeSet示例

下面通過實例學習如何使用TreeSet

?
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import java.util.*;
 
/**
 * @desc TreeSet的API測試
 *
 * @author skywang
 * @email [email protected]
 */
public class TreeSetTest {
 
  public static void main(String[] args) {
    testTreeSetAPIs();
  }
  
  // 測試TreeSet的api
  public static void testTreeSetAPIs() {
    String val;
 
    // 新建TreeSet
    TreeSet tSet = new TreeSet();
    // 將元素添加到TreeSet中
    tSet.add("aaa");
    // Set中不允許重復元素,所以只會保存一個“aaa”
    tSet.add("aaa");
    tSet.add("bbb");
    tSet.add("eee");
    tSet.add("ddd");
    tSet.add("ccc");
    System.out.println("TreeSet:"+tSet);
 
    // 打印TreeSet的實際大小
    System.out.printf("size : %d\n", tSet.size());
 
    // 導航方法
    // floor(小于、等于)
    System.out.printf("floor bbb: %s\n", tSet.floor("bbb"));
    // lower(小于)
    System.out.printf("lower bbb: %s\n", tSet.lower("bbb"));
    // ceiling(大于、等于)
    System.out.printf("ceiling bbb: %s\n", tSet.ceiling("bbb"));
    System.out.printf("ceiling eee: %s\n", tSet.ceiling("eee"));
    // ceiling(大于)
    System.out.printf("higher bbb: %s\n", tSet.higher("bbb"));
    // subSet()
    System.out.printf("subSet(aaa, true, ccc, true): %s\n", tSet.subSet("aaa", true, "ccc", true));
    System.out.printf("subSet(aaa, true, ccc, false): %s\n", tSet.subSet("aaa", true, "ccc", false));
    System.out.printf("subSet(aaa, false, ccc, true): %s\n", tSet.subSet("aaa", false, "ccc", true));
    System.out.printf("subSet(aaa, false, ccc, false): %s\n", tSet.subSet("aaa", false, "ccc", false));
    // headSet()
    System.out.printf("headSet(ccc, true): %s\n", tSet.headSet("ccc", true));
    System.out.printf("headSet(ccc, false): %s\n", tSet.headSet("ccc", false));
    // tailSet()
    System.out.printf("tailSet(ccc, true): %s\n", tSet.tailSet("ccc", true));
    System.out.printf("tailSet(ccc, false): %s\n", tSet.tailSet("ccc", false));
 
 
    // 刪除“ccc”
    tSet.remove("ccc");
    // 將Set轉換為數組
    String[] arr = (String[])tSet.toArray(new String[0]);
    for (String str:arr)
      System.out.printf("for each : %s\n", str);
 
    // 打印TreeSet
    System.out.printf("TreeSet:%s\n", tSet);
 
    // 遍歷TreeSet
    for(Iterator iter = tSet.iterator(); iter.hasNext(); ) {
      System.out.printf("iter : %s\n", iter.next());
    }
 
    // 刪除并返回第一個元素
    val = (String)tSet.pollFirst();
    System.out.printf("pollFirst=%s, set=%s\n", val, tSet);
 
    // 刪除并返回最后一個元素
    val = (String)tSet.pollLast();
    System.out.printf("pollLast=%s, set=%s\n", val, tSet);
 
    // 清空HashSet
    tSet.clear();
 
    // 輸出HashSet是否為空
    System.out.printf("%s\n", tSet.isEmpty()?"set is empty":"set is not empty");
  }
}

運行結果: 

?
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
TreeSet:[aaa, bbb, ccc, ddd, eee]
size : 5
floor bbb: bbb
lower bbb: aaa
ceiling bbb: bbb
ceiling eee: eee
higher bbb: ccc
subSet(aaa, true, ccc, true): [aaa, bbb, ccc]
subSet(aaa, true, ccc, false): [aaa, bbb]
subSet(aaa, false, ccc, true): [bbb, ccc]
subSet(aaa, false, ccc, false): [bbb]
headSet(ccc, true): [aaa, bbb, ccc]
headSet(ccc, false): [aaa, bbb]
tailSet(ccc, true): [ccc, ddd, eee]
tailSet(ccc, false): [ddd, eee]
for each : aaa
for each : bbb
for each : ddd
for each : eee
TreeSet:[aaa, bbb, ddd, eee]
iter : aaa
iter : bbb
iter : ddd
iter : eee
pollFirst=aaa, set=[bbb, ddd, eee]
pollLast=eee, set=[bbb, ddd]
set is empty

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产美女在线一区二区三区 | 日本高清免费中文字幕不卡 | 男人插曲女人身体 | 国产伦码精品一区二区 | 精品久久一区 | 女人扒开下面让男人桶爽视频 | 亚洲 无码 制服 日韩 | 国产hd老头老太婆 | 国产成人lu在线视频 | 欧美一二区视频 | 天天做天天爱天天爽综合区 | 全日爱韩国视频在线观看 | 女同videos双性人 | se01在线看片| 亚洲邪恶天堂影院在线观看 | 色综合中文字幕在线亚洲 | 国产精品久久久久这里只有精品 | 国产精品理论片 | 男女视频在线观看 | 臀控福利大臀的网站 | 免费岛国 | 波多野结衣中文字幕在线 | 双夫1v2 | 亚洲无人区乱码中文字幕 | beeg最新 | 朝鲜女人性猛交 | 被强迫调教的高辣小说 | 欧美日韩第二页 | 成人一级黄色大片 | 久久精品视在线观看2 | 91久久夜色精品国产九色 | 久久电影精品久久99久久 | 欧美同性猛男野外gay免费 | 国产在线xvideos | 91香蕉国产 | 5x社区在线观看直接进入 | 欧美成人一区二区 | 亚洲高清免费在线观看 | 国产尤物视频 | 亚洲欧美在线观看一区二区 | 欧美区一区|