Java Sets

The java.util.Set interface is a member of the Java Collections Framework and extends the java.util.Collection interface. It is an unordered collection of objects, in which duplicate values cannot be stored. Some of the common methods of the Set interface are:

add(E e): Adds the specified element to this set if it is not already present.
clear(): Removes all of the elements from this set.
contains(Object o): Returns true if this set contains the specified element.
isEmpty(): Returns true if this set contains no elements.
iterator(): Returns an iterator over the elements in this set.
remove(Object o): Removes the specified element from this set if it is present.
size(): Returns the number of elements in this set.

Here is an example of using some of these methods:

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

public class SetExample {
  public static void main(String[] args) {
    Set<String> set = new HashSet<>();
    
    // Add elements to the set
    set.add("apple");
    set.add("banana");
    set.add("cherry");
    set.add("apple");  // Duplicate element, not added to the set

    // Check if an element is in the set
    System.out.println("Is banana in the set? " + set.contains("banana"));
    System.out.println("Is mango in the set? " + set.contains("mango"));

    // Remove an element from the set
    set.remove("cherry");

    // Print the size of the set
    System.out.println("Size of the set: " + set.size());

    // Iterate over the elements in the set
    for (String s : set) {
      System.out.println(s);
    }
  }
}

There are several implementations of the Set interface in the Java Collections Framework,
including java.util.HashSet, java.util.LinkedHashSet, and java.util.TreeSet.
Each of these implementations has its own characteristics and performance trade-offs,
so you should choose the one that is most appropriate for your needs.

java.util.HashSet is a class that implements the Set interface and uses a hash table for storage. It offers constant-time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets. Iterating over the elements in a HashSet requires time proportional to the capacity of the set plus the number of elements in the set.

Here is an example of using a HashSet:

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

public class HashSetExample {
  public static void main(String[] args) {
    Set<String> set = new HashSet<>();
    
    set.add("apple");
    set.add("banana");
    set.add("cherry");
    set.add("apple");  // Duplicate element, not added to the set

    // Iterate over the elements in the set
    for (String s : set) {
      System.out.println(s);
    }
  }
}

java.util.LinkedHashSet is a class that extends HashSet and maintains a linked list of the elements in the set, in the order in which they were added. This allows insertion-order iteration over the elements in the set. It offers constant-time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets. Iterating over the elements in a LinkedHashSet requires time proportional to the number of elements in the set.

Here is an example of using a LinkedHashSet:

import java.util.Set;
import java.util.LinkedHashSet;

public class LinkedHashSetExample {
  public static void main(String[] args) {
    Set<String> set = new LinkedHashSet<>();
    
    set.add("apple");
    set.add("banana");
    set.add("cherry");
    set.add("apple");  // Duplicate element, not added to the set

    // Iterate over the elements in the set
    for (String s : set) {
      System.out.println(s);
    }
  }
}

java.util.HashSet is a class that implements the Set interface and uses a hash table for storage. It offers constant-time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets. Iterating over the elements in a HashSet requires time proportional to the capacity of the set plus the number of elements in the set.

Here is an example of using a HashSet:

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

public class HashSetExample {
  public static void main(String[] args) {
    Set<String> set = new HashSet<>();
    
    set.add("apple");
    set.add("banana");
    set.add("cherry");
    set.add("apple");  // Duplicate element, not added to the set

    // Iterate over the elements in the set
    for (String s : set) {
      System.out.println(s);
    }
  }
}

java.util.LinkedHashSet is a class that extends HashSet and maintains a linked list of the elements in the set, in the order in which they were added. This allows insertion-order iteration over the elements in the set. It offers constant-time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets. Iterating over the elements in a LinkedHashSet requires time proportional to the number of elements in the set.

Here is an example of using a LinkedHashSet:

import java.util.Set;
import java.util.LinkedHashSet;

public class LinkedHashSetExample {
  public static void main(String[] args) {
    Set<String> set = new LinkedHashSet<>();
    
    set.add("apple");
    set.add("banana");
    set.add("cherry");
    set.add("apple");  // Duplicate element, not added to the set

    // Iterate over the elements in the set
    for (String s : set) {
      System.out.println(s);
    }
  }
}

java.util.TreeSet is a class that implements the Set interface and uses a tree for storage. It provides guaranteed log(n) time cost for the basic operations (add, remove, contains and size). The elements in a TreeSet are sorted according to their natural ordering, or by a Comparator provided at set creation time.

Here is an example of using a TreeSet:

import java.util.Set;
import java.util.TreeSet;

public class TreeSetExample {
  public static void main(String[] args) {
    Set<String> set = new TreeSet<>();
    
    set.add("apple");
    set.add("banana");
    set.add("cherry");
    set.add("apple");  // Duplicate element, not added to the set

    // Iterate over the elements in the set
    for (String s : set) {
      System.out.out.println(s);
     }
  }
}

In summary, the main differences between HashSet, LinkedHashSet, and TreeSet are:

  • HashSet is implemented using a hash table and offers constant-time performance for the basic operations. It does not maintain the insertion order of the elements.
  • LinkedHashSet is implemented using a hash table and a linked list and offers constant-time performance for the basic operations. It maintains the insertion order of the elements.
  • TreeSet is implemented using a tree and offers log(n) time performance for the basic operations. It maintains the elements in sorted order according to their natural ordering or a provided Comparator.

You should choose the implementation that is most appropriate for your needs based on these characteristics.

The information I provided about the java.util.Set interface and its implementations, java.util.HashSet, java.util.LinkedHashSet, and java.util.TreeSet, is based on the official Java API documentation for these classes.
You can find more information about these classes and their methods in the Java SE 11 API documentation, which is available online at the following URL:

java.util.Set: https://docs.oracle.com/en/java/javase/11/docs/api/java.util/Set.html
java.util.HashSet: https://docs.oracle.com/en/java/javase/11/docs/api/java.util/HashSet.html
java.util.LinkedHashSet: https://docs.oracle.com/en/java/javase/11/docs/api/java.util/LinkedHashSet.html
java.util.TreeSet: https://docs.oracle.com/en/java/javase/11/docs/api/java.util/TreeSet.html
I also provided examples of using these classes to illustrate their functionality. These examples are meant to be general and may not reflect the exact behavior of these classes in all situations.