View Javadoc
1   package fr.univtln.bruno.samples.java101.tp3.set;
2   
3   import fr.univtln.bruno.samples.java101.tp3.Person;
4   import lombok.extern.slf4j.Slf4j;
5   
6   import java.util.*;
7   
8   /**
9    * Examples demonstrating Set implementations and common set operations.
10   *
11   * <p>Illustrates HashSet/LinkedHashSet/TreeSet characteristics, set algebra (union/intersection/difference),
12   * and immutability patterns.</p>
13   */
14  @Slf4j
15  public class SetExamples {
16    /**
17     * Private constructor to prevent instantiation.
18     */
19    private SetExamples() {
20    }
21  
22    /**
23     * Demonstrates HashSet usage, including duplicate handling and iteration.
24     * The Person class must correctly implement equals() and hashCode() for this to work as expected.
25     * In case of a TreeSet instead of HashSet, Person must implement Comparable<Person>.
26     */
27    public static void hashSetExample() {
28      log.info("=== HashSet Example ===");
29      Set<Person> people = new HashSet<>();
30      people.add(Person.of("Alice", "Smith", 30));
31      people.add(Person.of("Bob", "Jones", 25));
32      people.add(Person.of("Charlie", "Brown", 35));
33      boolean addedDuplicate = people.add(Person.of("Alice", "Smith", 30));
34      log.debug("HashSet internal state after adds: {}", people);
35      log.info("Duplicate added? {}", addedDuplicate);
36      log.info("Size: {}", people.size());
37      people.forEach(p -> log.info("Person: {}", p.getFullName()));
38    }
39  
40    /**
41     * Demonstrates LinkedHashSet usage to maintain insertion order.
42     * Person class must implement equals() and hashCode() correctly.
43     * LinkedHashSet preserves the order in which elements were added.
44     */
45    public static void linkedHashSetExample() {
46      log.info("=== LinkedHashSet Example ===");
47      Set<String> ordered = new LinkedHashSet<>(List.of("C", "A", "B"));
48      ordered.forEach(s -> log.info("Order: {}", s));
49    }
50  
51    /**
52     * Demonstrates TreeSet usage for sorting elements, both natural and by custom comparator.
53     * Person class must implement Comparable<Person> for natural ordering.
54     */
55    public static void treeSetExample() {
56      log.info("=== TreeSet Example ===");
57      Set<Person> sorted = new TreeSet<>();
58      sorted.add(Person.of("Charlie", "Brown", 35));
59      sorted.add(Person.of("Alice", "Smith", 30));
60      sorted.add(Person.of("Bob", "Jones", 25));
61      log.debug("TreeSet elements (iteration order): {}", sorted);
62      sorted.forEach(p -> log.info("Sorted: {}", p.getFullName()));
63      Set<Person> byAge = new TreeSet<>(Comparator.comparing(Person::age));
64      byAge.addAll(sorted);
65      log.debug("Age-sorted set: {}", byAge);
66      byAge.forEach(p -> log.info("AgeSorted: {} ({})", p.getFullName(), p.age()));
67    }
68  
69    /**
70     * Demonstrates common set operations: union, intersection, difference, and symmetric difference.
71     */
72    public static void setOperationsExample() {
73      log.info("=== Set Operations Example ===");
74      Set<String> s1 = new HashSet<>(Set.of("A", "B", "C", "D"));
75      Set<String> s2 = new HashSet<>(Set.of("C", "D", "E", "F"));
76      Set<String> union = new HashSet<>(s1);
77      union.addAll(s2);
78      Set<String> inter = new HashSet<>(s1);
79      inter.retainAll(s2);
80      Set<String> diff = new HashSet<>(s1);
81      diff.removeAll(s2);
82      Set<String> sym = new HashSet<>(union);
83      sym.removeAll(inter);
84      log.debug("s1={}, s2={}", s1, s2);
85      log.info("Union: {}", union);
86      log.info("Inter: {}", inter);
87      log.info("Diff: {}", diff);
88      log.info("SymDiff: {}", sym);
89    }
90  
91    /**
92     * Demonstrates removal of duplicates from a collection using Set implementations.
93     */
94    public static void removeDuplicatesExample() {
95      log.info("=== Remove Duplicates ===");
96      List<String> withDup = List.of("A", "B", "A", "C", "B", "D");
97      fr.univtln.bruno.samples.java101.tp3.set.DedupCollections.removeDuplicatesPreserveOrder(withDup);
98    }
99  
100   /**
101    * Demonstrates NavigableSet features like navigation methods and descending view.
102    * A NavigableSet is a SortedSet with additional navigation methods : lower, floor, ceiling, higher, and descendingSet.
103    */
104   public static void navigableSetExample() {
105     log.info("=== NavigableSet Example ===");
106     NavigableSet<Integer> nav = new TreeSet<>(Set.of(1, 3, 5, 7, 9));
107     log.info("Lower(7): {} Floor(7): {} Ceiling(7): {} Higher(7): {}", nav.lower(7), nav.floor(7), nav.ceiling(7), nav.higher(7));
108     log.info("Desc: {}", nav.descendingSet());
109   }
110   /**
111    * Main method to run all examples.
112    */
113 
114   /**
115    * Demonstrates immutable Set creation and attempts to modify it.
116    */
117   public static void immutableSetExample() {
118     log.info("=== ImmutableSet Example ===");
119     Set<String> imm = Set.of("A", "B", "C");
120     try {
121       imm.add("D");
122     } catch (UnsupportedOperationException e) {
123       log.info("Immutable cannot add");
124     }
125     Set<String> mutable = new HashSet<>(Set.of("X", "Y"));
126     Set<String> view = Collections.unmodifiableSet(mutable);
127     mutable.add("Z");
128     log.info("View reflects mutable: {}", view);
129   }
130 
131   /**
132    * Runner for set examples.
133    *
134    * @param args ignored
135    */
136   public static void main(String[] args) {
137     hashSetExample();
138     linkedHashSetExample();
139     treeSetExample();
140     setOperationsExample();
141     removeDuplicatesExample();
142     immutableSetExample();
143     navigableSetExample();
144   }
145 }