-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTreeSetDemo.java
More file actions
150 lines (134 loc) · 5.89 KB
/
Copy pathTreeSetDemo.java
File metadata and controls
150 lines (134 loc) · 5.89 KB
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
package Phase5_CollectionsLambdasStreams.Collections;
import java.util.*;
/**
* java.util.TreeSet<E> - Sorted Set Backed by a Red-Black Tree
* ------------------------------------------------------------
* TreeSet keeps its elements in SORTED ORDER, using either:
* - the natural ordering (E must implement Comparable<E>), or
* - a Comparator<E> you provide at construction.
* <p>
*
* Why It Exists
* -------------
* - Iteration is always in sorted order, no extra sort needed.
* - Range queries (subSet / headSet / tailSet) are O(log n).
* - "Nearest neighbour" lookups (floor / ceiling / lower / higher) are
* O(log n) and unique to TreeSet.
* <p>
*
* When To Use It
* --------------
* - You need elements in sorted order on every iteration.
* - You ask range / neighbour questions: "all events between 10 AM and
* noon", "smallest score >= 60", "largest price under $100".
* <p>
*
* For pure "is this in my set?" with no ordering needs, HashSet is
* faster: O(1) vs O(log n).
* <p>
*
* Big-O
* -----
* add / remove / contains O(log n)
* iteration (in order) O(n)
* first / last / floor / ceiling / lower / higher O(log n)
* range views (sub / head / tail) O(log n) to create, O(k) to iterate
* <p>
*
* Constructors
* ------------
* new TreeSet<>()
* new TreeSet<>(Comparator<? super E>)
* new TreeSet<>(Collection<? extends E>)
* new TreeSet<>(SortedSet<E>)
* <p>
*
* Key Methods (Beyond the Inherited Set Contract)
* -----------------------------------------------
* - SortedSet:
* first() / last()
* headSet(toE) - strictly less
* tailSet(fromE) - fromE inclusive
* subSet(fromE, toE) - fromE inclusive, toE exclusive
* comparator()
* <p>
*
* - NavigableSet:
* floor(e) - greatest element <= e
* ceiling(e) - smallest element >= e
* lower(e) - greatest element < e
* higher(e) - smallest element > e
* pollFirst() / pollLast()
* descendingIterator() / descendingSet()
* navigableHeadSet / Tail / SubSet (with inclusive flags)
*/
public class TreeSetDemo {
record Person(String name, int age) implements Comparable<Person> {
@Override
public int compareTo(Person o) {
// Natural order: by age first, then by name.
int c = Integer.compare(age, o.age);
return c != 0 ? c : name.compareTo(o.name);
}
}
public static void main(String[] args) {
section("1) Natural-order sort of primitives");
TreeSet<Integer> nums = new TreeSet<>(List.of(5, 1, 4, 2, 3, 1));
System.out.println("set = " + nums); // [1, 2, 3, 4, 5]
System.out.println("first() = " + nums.first());
System.out.println("last() = " + nums.last());
System.out.println("size = " + nums.size());
section("2) Custom comparator at construction");
TreeSet<String> byLen = new TreeSet<>(
Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder())
);
byLen.add("date");
byLen.add("fig");
byLen.add("apple");
byLen.add("kiwi");
System.out.println("by length = " + byLen);
section("3) Sub-set views - LIVE views, share state with the parent");
NavigableSet<Integer> ns = new TreeSet<>(List.of(10, 20, 30, 40, 50, 60));
SortedSet<Integer> head = ns.headSet(30); // [10, 20]
SortedSet<Integer> tail = ns.tailSet(30); // [30, 40, 50, 60]
SortedSet<Integer> sub = ns.subSet(20, 50); // [20, 30, 40]
System.out.println("headSet(30)= " + head);
System.out.println("tailSet(30)= " + tail);
System.out.println("subSet(20,50)= " + sub);
sub.add(25); // mutates ns too
System.out.println("ns after sub.add(25) = " + ns);
section("4) Neighbour queries on NavigableSet");
System.out.println("floor(35) = " + ns.floor(35)); // 30
System.out.println("ceiling(35)= " + ns.ceiling(35)); // 40
System.out.println("lower(30) = " + ns.lower(30)); // 25
System.out.println("higher(30) = " + ns.higher(30)); // 40
section("5) pollFirst / pollLast - remove and return");
System.out.println("pollFirst()= " + ns.pollFirst() + " set=" + ns);
System.out.println("pollLast() = " + ns.pollLast() + " set=" + ns);
section("6) descendingSet - reverse view");
TreeSet<Integer> small = new TreeSet<>(List.of(3, 1, 2));
System.out.println("ascending = " + small);
System.out.println("descending = " + small.descendingSet());
section("7) Custom objects via Comparable");
TreeSet<Person> people = new TreeSet<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Carol", 30));
people.add(new Person("Dave", 22));
for (Person p : people) System.out.println(" " + p);
section("8) Custom objects via Comparator (override natural order)");
TreeSet<Person> byNameDesc = new TreeSet<>(Comparator.comparing(Person::name).reversed());
byNameDesc.addAll(people);
byNameDesc.forEach(p -> System.out.println(" " + p));
section("9) Range queries on objects");
Person low = new Person("", 25);
Person high = new Person("z", 30); // pick boundary values
// Find everyone aged 25..29 inclusive
SortedSet<Person> range = people.subSet(low, high);
range.forEach(p -> System.out.println(" in range: " + p));
// OUTPUT (representative)
}
private static void section(String title) {
System.out.println("\n====== " + title + " ======");
}
}