devstory

Le Tutoriel de Java Set

  1. Set
  2. Simple Examples
  3. stream()
  4. iterator()
  5. Comment Set vérifie-t-il la duplication?
  6. of(..)
  7. spliterator()
  8. toArray​(..)

1. Set

Set est une interface dans Java Collection Framework, et est une sous-interface de Collection, il dispose donc de toutes les fonctionnalités d'une Collection.
Setest une Collection non ordonnée, laquelle n'autorise pas les éléments dupliqués et contient au maximum 1 élément null. Si vous ajoutez intentionnellement un élément dupliqué à Set, cette action sera activée et Set ne changera pas.
public interface Set<E> extends Collection<E>
SortedSetest une sous-interface de Set. Il est capable de trier automatiquement les éléments en fonction de leur ordre naturel ou par un Comparator fourni.
La hiérarchie des classes implémente l'interface Set.
Les méthodes de l'interface Set:
Set interface
boolean add​(E e)  
boolean addAll​(Collection<? extends E> c)  

void clear()  

boolean contains​(Object o)  
boolean containsAll​(Collection<?> c)  

boolean equals​(Object o)  
int hashCode()  
boolean isEmpty()  
int size()  

boolean remove​(Object o)  
boolean removeAll​(Collection<?> c)  
boolean retainAll​(Collection<?> c)  

Object[] toArray()  
<T> T[] toArray​(T[] a)

Iterator<E> iterator()  
default Spliterator<E> spliterator()  

static <E> Set<E> copyOf​(Collection<? extends E> coll)  

static <E> Set<E> of()  
static <E> Set<E> of​(E e1)  
static <E> Set<E> of​(E... elements)  
static <E> Set<E> of​(E e1, E e2)  
static <E> Set<E> of​(E e1, E e2, E e3)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5, E e6)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5, E e6, E e7)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)

2. Simple Examples

Setest une interface. Par conséquent, pour créer un objet Set, vous devez créer via une classe qui l'implémente, telle que HashSet, LinkedHashSet, TreeSet, etc.
Dans l'exemple ci-dessous, il faut créer un objet HashSet avec une capacité initiale de 10 éléments, et la capacité augmentera de 80% si le nombre d'éléments dépasse la capacité actuelle.
SetEx1.java
package org.o7planning.set.ex;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class SetEx1 {

    public static void main(String[] args) {
        Set<String> set = new HashSet<String>(10, (float) 0.8);

        set.add("One");
        set.add("Two");
        set.add("Three");
        
        Iterator<String> it1 = set.iterator();
        while (it1.hasNext()) {
            System.out.println(it1.next());
        }
        
        System.out.println(" ----- ");
        
        // When duplication occurs.
        // It will add new element and remove old element.
        set.add("Two");
        set.add("Four");

        Iterator<String> it2 = set.iterator();
        while (it2.hasNext()) {
            System.out.println(it2.next());
        }
    }
}
Remarque: Set est une Collection non ordonnée, par conséquent, vous pouvez recevoir un résultat légèrement différent lorsque vous imprimez les éléments à l'écran Console.
Output:
One
Two
Three
 -----
One
Four
Two
Three
Array --> Set?
Un exemple de conversion d'un tableau en un objet Set.
ArrayToSetEx.java
package org.o7planning.set.ex;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class ArrayToSetEx {
    
    public static void main(String[] args) {
        Integer[] sourceArray = { 0, 3, 5, 3, 4, 5 };
        
        Set<Integer> targetSet = new HashSet<Integer>(Arrays.asList(sourceArray));
    
        for(Integer i : targetSet)  {
            System.out.println(i);
        }
    }  
}
Output:
0
3
4
5

3. stream()

Setest une sous-interface de Collection, il hérite donc de la méthode stream(). L'accès aux éléments d'une Collection via Stream rend bref et facile à comprendre votre code:
Set_stream.java
package org.o7planning.set.ex;

import java.util.HashSet;
import java.util.Set;

public class Set_stream {

    public static void main(String[] args) {  
        Set<String> set = new HashSet<String>();
        
        set.add("a1");
        set.add("b1");
        set.add("a2");  
        set.add("c1");  
        set.add("d1");  
        set.add("e1");  
        
        set.stream() //
              .map(String::toUpperCase) // to upsercase
              .filter(s -> !s.startsWith("A")) // Not starts with "A".
              .forEach(System.out::println);  
    }  
}
Output:
E1
D1
C1
B1

4. iterator()

iterator() est une méthode héritant de Collection, retournant un objet Iterator pour itérer les éléments de Collection.
Iterator<E> iterator()
Set_iterator.java
package org.o7planning.set.ex;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Set_iterator {

    public static void main(String[] args) {  
        Set<String> set = new HashSet<String>();
        
        set.add("a1");
        set.add("b1");
        set.add("a2");  
        
        Iterator<String> ite = set.iterator();
        
        while(ite.hasNext()) {
            System.out.println(ite.next());
        }
    }  
}
Output:
a1
a2
b1

5. Comment Set vérifie-t-il la duplication?

Set est une Collectionqui ne permet pas de contenir des éléments dupliqués. Si vous ajoutez intentionnellement un élément dupliqué à Set, cette action sera ignorée. La question est donc: comment "Set" vérifie-t-il la duplication?
SortedSet est une sous-interface de Set. Dans cette section, nous nous référons uniquement à Setpur (pas à SortedSet). Les classes qui représentent un Set pur sont HashSet, LinkedHashSet, CopyOnWriteArraySet et EnumSet.
La manière dont SortedSet vérifie la duplication est complètement différente de Set pur et est traitée dans l'article ci-dessous:
HashSet / LinkedHashSet
HashSet (et LinkedHashSet) compare le hashcode de deux éléments, ensuite compare les deux éléments directement via leur méthode equals.
Observer deux exemples ci-dessous sur HashSetDupTest1 & HashSetDupTest2 pour mieux comprendre sur la description ci-dessus.
HashSetDupTest1.java
package org.o7planning.set.test;

import java.util.HashSet;
import java.util.Set;

public class HashSetDupTest1 {

    public static class Student {
        private int studentId;
        private String studentName;
        
        public Student(int studentId, String studentName) {
            this.studentId = studentId;
            this.studentName = studentName;
        }
        public int getStudentId() {
            return studentId;
        }
        public String getStudentName() {
            return studentName;
        }
        @Override
        public boolean equals(Object other)  {
            if(other == null || !(other instanceof Student)) {
                return false;
            }
            Student o = (Student) other;
            return this.studentId == o.studentId;
        }
    }
    
    public static void main(String[] args) {
        Student s1 = new Student(1, "Tom");
        Student s2 = new Student(2, "Jerry");
        Student s3 = new Student(1, "Tom Cat"); // Same Id with s1.
        
        Set<Student> set = new HashSet<Student>();
        
        set.add(s1);
        set.add(s2);
        set.add(s3);

        for(Student s: set)  {
            System.out.printf("Student Id: %d / Name: %s (Hashcode: %s)\n", //
                    s.getStudentId(),s.getStudentName(),s.hashCode());
        }
    }
}
Output:
Student Id: 2 / Name: Jerry (Hashcode: 474675244)
Student Id: 1 / Name: Tom Cat (Hashcode: 932583850)
Student Id: 1 / Name: Tom (Hashcode: 1586600255)
Modifier l'exemple ci-dessus en remplaçant (override) la méthode hashCode() dans la classe Student:
HashSetDupTest2.java
package org.o7planning.set.test;

import java.util.HashSet;
import java.util.Set;

public class HashSetDupTest2 {

    public static class Student {
        private int studentId;
        private String studentName;
        
        public Student(int studentId, String studentName) {
            this.studentId = studentId;
            this.studentName = studentName;
        }
        public int getStudentId() {
            return studentId;
        }
        public String getStudentName() {
            return studentName;
        }
        @Override
        public boolean equals(Object other)  {
            if(other == null || !(other instanceof Student)) {
                return false;
            }
            Student o = (Student) other;
            return this.studentId == o.studentId;
        }
        @Override
        public int hashCode() { // -----> Override hashCode() method.
            return this.studentName.charAt(0);
        }
    }
    
    public static void main(String[] args) {
        Student s1 = new Student(1, "Tom");   // Hashcode: 84 ('T')
        Student s2 = new Student(1, "Tom Cat"); // Hashcode: 84 ('T')
        
        Student s3 = new Student(2, "Jerry"); // Hashcode: 74 ('J')
        
        Student s4 = new Student(4, "Daffy"); // Hashcode: 68 ('D')
        Student s5 = new Student(5, "Donald"); // Hashcode: 68 ('D')
        
        
        Set<Student> set = new HashSet<Student>();
        
        set.add(s1);
        set.add(s2); // a Duplication (Ignored!)
        set.add(s3);
        set.add(s4);  
        set.add(s5);  

        for(Student s: set)  {
            System.out.printf("Student Id: %d / Name: %s (Hashcode: %s)\n", //
                    s.getStudentId(),s.getStudentName(),s.hashCode());
        }
    }
}
Output:
Student Id: 1 / Name: Tom (Hashcode: 84)
Student Id: 4 / Name: Daffy (Hashcode: 68)
Student Id: 5 / Name: Donald (Hashcode: 68)
Student Id: 2 / Name: Jerry (Hashcode: 74)
CopyOnWriteArraySet
CopyOnWriteArraySet compare directement 2 éléments via leur méthode equals.
Observer 2 exemples CopyOnWriteArraySetDupTest1 & CopyOnWriteArraySetDupTest2 ci-dessous pour en savoir plus sur la description ci-dessus.
CopyOnWriteArraySetDupTest1.java
package org.o7planning.set.test;

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

public class CopyOnWriteArraySetDupTest1 {

    public static class Employee {
        private int empId;
        private String empName;
        
        public Employee(int empId, String empName) {
            this.empId = empId;
            this.empName = empName;
        }
        public int getEmpId() {
            return empId;
        }
        public String getEmpName() {
            return empName;
        }
        // Employee class uses equals(Object) method inherited from Object class.
    }
    
    public static void main(String[] args) {
        Employee s1 = new Employee(1, "Tom");    
        Employee s2 = new Employee(2, "Jerry");  
        Employee s3 = new Employee(1, "Tom Cat");  
        
        Set<Employee> set = new CopyOnWriteArraySet<Employee>();
        
        set.add(s1);
        set.add(s2);
        set.add(s3);  

        for(Employee s: set)  {
            System.out.printf("Emp Id: %d / Name: %s\n", //
                    s.getEmpId(),s.getEmpName());
        }
    }
}
Output:
Emp Id: 1 / Name: Tom
Emp Id: 2 / Name: Jerry
Emp Id: 1 / Name: Tom Cat
Modifier l'exemple ci-dessus en remplaçant (override) la méthode equals(Object) dans la classe Employee:
CopyOnWriteArraySetDupTest2.java
package org.o7planning.set.test;

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

public class CopyOnWriteArraySetDupTest2 {

    public static class Employee {
        private int empId;
        private String empName;
        
        public Employee(int studentId, String studentName) {
            this.empId = studentId;
            this.empName = studentName;
        }
        public int getEmpId() {
            return empId;
        }
        public String getEmpName() {
            return empName;
        }
        @Override
        public boolean equals(Object other)  { // -----> Override equals() method.
            if(other == null || !(other instanceof Employee)) {
                return false;
            }
            Employee o = (Employee) other;
            return this.empId == o.empId;
        }
    }
    
    public static void main(String[] args) {
        Employee s1 = new Employee(1, "Tom");   
        Employee s2 = new Employee(2, "Jerry");  
        Employee s3 = new Employee(1, "Tom Cat");
        
        Set<Employee> set = new CopyOnWriteArraySet<Employee>();
        
        set.add(s1);
        set.add(s2);
        set.add(s3); // a Duplication.

        for(Employee s: set)  {
            System.out.printf("Emp Id: %d / Name: %s\n", //
                    s.getEmpId(),s.getEmpName());
        }
    }
}
Output:
Emp Id: 1 / Name: Tom
Emp Id: 2 / Name: Jerry

6. of(..)

La méthode statique Set.of(..) renvoie un objet Set de taille fixe, l'exception est levée si les paramètres d'entrée sont dupliqués. Cet objet Set ne supporte pas les méthodes facultatives: add, remove, set et clear.
static <E> Set<E> of()  
static <E> Set<E> of​(E e1)  
static <E> Set<E> of​(E... elements)  
static <E> Set<E> of​(E e1, E e2)  
static <E> Set<E> of​(E e1, E e2, E e3)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5, E e6)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5, E e6, E e7)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9)  
static <E> Set<E> of​(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)
Set_of.java
package org.o7planning.set.ex;

import java.util.Iterator;
import java.util.Set;

public class Set_of {

    public static void main(String[] args) {
        Set<Integer> set = Set.of(1, 2, 5, 3, 7, 9, 0);

        Iterator<Integer> it2 = set.iterator();
        while (it2.hasNext()) {
            System.out.println(it2.next());
        }
    }
}
Remarque: Setest une Collection non ordonnée, par conséquent, vous pouvez obtenir un résultat légèrement différent lors de l'impression d'éléments à l'écran Console.
Output:
2
3
5
7
9
0
1

7. spliterator()

Créer un objet Spliterator pour parcourir et partitionner les éléments de Set.
default Spliterator<E> spliterator()
Spliterator est largement utilisé pour parcourir et partitionner de nombreuses sources de données différentes telles que Collection (List, Set, Queue), BaseStream, array.
  • Java Spliterator

8. toArray​(..)

La méthode toArray(..) renvoie un tableau contenant tous les éléments de Set.
Object[] toArray()  

<T> T[] toArray​(T[] a)

// Java 11, The default method, inherited from Collection.
default <T> T[] toArray​(IntFunction<T[]> generator)
Set_toArray.java
package org.o7planning.set.ex;

import java.util.HashSet;
import java.util.Set;

public class Set_toArray {

    public static void main(String[] args) {  
        Set<String> set = new HashSet<String>();
        
        set.add("a1");
        set.add("b1");
        set.add("a2");  
        
        String[] array = new String[set.size()];
        
        set.toArray(array);
        
        for(String s: array) {
            System.out.println(s);
        }
    }  
}
Output:
a1
a2
b1