Showing posts with label Java set. Show all posts
Showing posts with label Java set. Show all posts

Thursday, March 2, 2023

ConcurrentSkipListSet in Java With Examples

ConcurrentSkipListSet in Java is a scalable concurrent set in Java which uses ConcurrentSkipListMap internally. Though concurrent collections like ConcurrentHashMap and CopyOnWriteArraySet were added in Java 1.5, ConcurrentSkipListSet and the similar map implementation ConcurrentSkipListMap were added in Java 1.6.

ConcurrentSkipListSet in Java

Since ConcurrentSkipListSet implements NavigableSet in Java, it is a sorted set just like TreeSet with added feature of being concurrent. Which essentially means it is a sorted data structure which can be used by multiple threads concurrently where as TreeSet is not thread safe.

The elements of the ConcurrentSkipListSet are kept sorted according to their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used.

Java ConcurrentSkipListSet constructors

  • ConcurrentSkipListSet()- Constructs a new, empty set that orders its elements according to their natural ordering.
  • ConcurrentSkipListSet(Collection<? extends E> c)- Constructs a new set containing the elements in the specified collection, that orders its elements according to their natural ordering.
  • ConcurrentSkipListSet(Comparator<? super E> comparator)- Constructs a new, empty set that orders its elements according to the specified comparator.
  • ConcurrentSkipListSet(SortedSet<E> s)- Constructs a new set containing the same elements and using the same ordering as the specified sorted set.Paste your text here.

Java ConcurrentSkipListSet performance

ConcurrentSkipListSet implementation provides expected average log(n) time cost for the contains, add, and remove operations and their variants. Insertion, removal, and access operations safely execute concurrently by multiple threads.

No Nulls in ConcurrentSkipListSet

ConcurrentSkipListSet does not permit the use of null elements, because null arguments and return values cannot be reliably distinguished from the absence of elements.

ConcurrentSkipListSet Java example

Let's see an example where we add some values in a ConcurrentSkipListSet and in the output it can be seen that the elements are sorted. In this example elements are of type String and for String natural ordering is ascending alphabetical order. So when you iterate the set you'll see it is in sorted same way.

Note that ConcurrentSkipListSet like any other set implementation i.e. HashSet can only store unique elements. Also, as mentioned internally it uses ConcurrentSkipListMap so when you call add method of ConcurrentSkipListSet it will in turn call putIfAbsent() method of the concurrentMap, that way element is stored only if it is not there already.

import java.util.Iterator;
import java.util.NavigableSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class CSSDemo {
  public static void main(String[] args) {
    NavigableSet<String> citySet = new ConcurrentSkipListSet<String>();
    citySet.add("New Delhi");
    citySet.add("Mumbai");
    citySet.add("Chennai");
    citySet.add("Hyderabad");
    
    System.out.println("---- Traversing the set-----");
    Iterator<String> itr = citySet.iterator();
    while(itr.hasNext()){
      System.out.println("Value -  " + itr.next());
    }
  }
}

Output

---- Traversing the set-----
Value -  Chennai
Value -  Hyderabad
Value -  Mumbai
Value -  New Delhi

Navigable methods in ConcurrentSkipListSet

As already mentioned ConcurrentSkipListSet in Java implements NavigableSet interface so it has many navigation methods returning the closest matches for given search targets. Let's see some of them in example code.

  • higher(E e)- Returns the least element in this set strictly greater than the given element, or null if there is no such element.
  • lower(E e)- Returns the greatest element in this set strictly less than the given element, or null if there is no such element.
  • tailSet(E fromElement)- Returns a view of the portion of this set whose elements are greater than or equal to fromElement.
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;

public class CSSDemo {
  public static void main(String[] args) {
    NavigableSet<String> citySet = new ConcurrentSkipListSet<String>();
    citySet.add("New Delhi");
    citySet.add("Mumbai");
    citySet.add("Chennai");
    citySet.add("Hyderabad");
    
    System.out.println("---- Traversing the set-----");
    Iterator<String> itr = citySet.iterator();
    while(itr.hasNext()){
      System.out.println("Value -  " + itr.next());
    }
        
    System.out.println("Higher - " + citySet.higher("C"));    
    System.out.println("Lower - " + citySet.lower("Mumbai"));    
    System.out.println("---- Tail Set -----");
    
    Set<String> set = citySet.tailSet("Hyderabad");    
    itr = set.iterator();
    while(itr.hasNext()){
      System.out.println("Value -  " + itr.next());
    }
  }
}

Output

---- Traversing the set-----
Value -  Chennai
Value -  Hyderabad
Value -  Mumbai
Value -  New Delhi
Higher - Chennai
Lower - Hyderabad
---- Tail Set -----
Value -  Hyderabad
Value -  Mumbai
Value -  New Delhi

Here higher as the description says is returning the least element in this set strictly greater than the given element. Since given element is "C" so returned value is "Chennai". Note that passed element doesn't have to be the one already present in set as here "C" is passed which is not an element of the Set.

lower as the description says is returning the greatest element in this set strictly less than the given element. Passed element is "Mumbai" so that returned element is "Hyderabad".

That's all for this topic ConcurrentSkipListSet in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentHashMap in Java With Examples
  2. CopyOnWriteArraySet in Java With Examples
  3. Java ArrayBlockingQueue With Examples
  4. Java CountDownLatch With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. How to Sort Elements in Different Order in TreeSet
  2. How to Sort HashSet in Java
  3. Difference Between Comparable and Comparator in Java
  4. Interface Default Methods in Java
  5. Java ThreadLocal Class With Examples
  6. Deadlock in Java Multi-Threading
  7. static Import in Java With Examples
  8. Difference Between throw And throws in Java

Sunday, August 14, 2022

Unmodifiable or Immutable Set in Java

A Set is considered unmodifiable if elements cannot be added, removed, or replaced from the Set once the unmodifiable instance of a Set is created. In this post we’ll see how Unmodifiable Set was created before Java 9 and how it can be created Java 9 onward using Immutable Set Static Factory Methods.

Creating Unmodifiable Set before Java 9

Till Java 8 in order to create unmodifiable Set Collections.unmodifiableSet() method was used.

  • Collections.unmodifiableSet(Set<? extends T> s)- Returns an unmodifiable view of the specified set.

Drawback of this method is that the underlying Set is still modifiable let’s try to see it with an example.

public class UnmodifiableSet {
  public static void main(String[] args) {
    Set<String> alphaSet = new HashSet<>();
    alphaSet.add("a");
    alphaSet.add("b");
    alphaSet.add("c");
    alphaSet.add("d");
    Set<String> aSet = Collections.unmodifiableSet(alphaSet);
    alphaSet.add("e");
    System.out.println("alphaSet- " + alphaSet);
    //error as this set is an unmodifiable view
    aSet.add("f");
  }
}

Output

alphaSet- [a, b, c, d, e] Exception in thread "main" 
java.lang.UnsupportedOperationException
 at java.base/java.util.Collections$UnmodifiableCollection.add(Collections.java:1058)
 at org.netjs.Programs.UnmodifiableSet.main(UnmodifiableSet.java:19)

In the example aSet is an unmodifiable view of the alphaSet. You can still modify the underlying set alphaSet though error is thrown if any modification is done to the unmodifiable view.

Creating Unmodifiable Set in Java 9

The Set.of (added in Java 9) and Set.copyOf (added in Java 10) Immutable static factory methods provide a convenient way to create unmodifiable sets. The Set instances created by these methods have the following characteristics-

  1. The Set returned by the convenience factory method added in JDK 9 is conventionally immutable. Elements cannot be added, removed, or replaced from such a Set. Calling any mutator method on the Set will always cause UnsupportedOperationException to be thrown.
  2. If the contained elements in the Set are mutable, this may cause the Set's contents to appear to change.
  3. Immutable Sets created using static factory methods disallow null elements. Attempts to create them with null elements result in NullPointerException.
  4. They reject duplicate elements at Immutable Set creation time. Duplicate elements passed to a static factory method result in IllegalArgumentException.
  5. They are serializable if all elements are serializable.
  6. The iteration order of set elements is unspecified and is subject to change.

Java Set.of() methods for creating unmodifiable set

Set.of() static factory method is a convenient way to create unmodifiable sets Java 9 onward. This method has both fixed-argument form and varargs form. Fixed-argument form overloads up to 10 elements and the form of this method is as follows.

Set.of()- Returns an unmodifiable set containing zero elements. 
Set.of(E e1)- Returns an unmodifiable set containing one element.
..
..
Set.of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9)- Returns an unmodifiable set containing nine elements. 
Set.of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)- Returns an unmodifiable set containing ten elements.

varargs form

  • Set.of(E... elements)- Returns an unmodifiable set containing an arbitrary number of elements.

Set.of() method Java example

public class UnmodifiableSet {
  public static void main(String[] args) {
    Set<String> alphaSet = Set.of("a", "b", "c", "d");
    System.out.println("alphaSet- " + alphaSet);
    //error as this set itself is immutable
    alphaSet.add("e");
  }
}

Output

alphaSet- [d, c, b, a]
Exception in thread "main" java.lang.UnsupportedOperationException
 at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:72)
 at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:76)
 at org.netjs.Programs.UnmodifiableSet.main(UnmodifiableSet.java:13)

Set.copyOf() method in Java

If you want to create an unmodifiable Set using an existing collection then you can use copyOf() method.

public class UnmodifiableSet {
  public static void main(String[] args) {
    Set<String> alphaSet = new HashSet<>();
    alphaSet.add("a");
    alphaSet.add("b");
    alphaSet.add("c");
    alphaSet.add("d");
    System.out.println("alphaSet- " + alphaSet);
    Set<String> aSet = Set.copyOf(alphaSet);
    System.out.println("aSet- " + alphaSet);
    //error as this set is unmodifiable
    aSet.add("f");
  }
}

Output

alphaSet- [a, b, c, d]
aSet- [a, b, c, d]
Exception in thread "main" java.lang.UnsupportedOperationException
 at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:72)
 at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:76)
 at org.netjs.Programs.UnmodifiableSet.main(UnmodifiableSet.java:19)

That's all for this topic Unmodifiable or Immutable Set in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How HashSet Works Internally in Java
  2. How to Sort HashSet in Java
  3. CopyOnWriteArraySet in Java With Examples
  4. Unmodifiable or Immutable List in Java
  5. Java Collections Interview Questions And Answers

You may also like-

  1. Java ArrayBlockingQueue With Examples
  2. Synchronization in Java - Synchronized Method And Block
  3. Optional Class in Java With Examples
  4. Array in Java With Examples
  5. static Block in Java
  6. Configuring DataSource in Spring Framework
  7. Spring MVC Excel Generation Example
  8. Class And Object in Python

Wednesday, May 18, 2022

LinkedHashSet in Java With Examples

LinkedHashSet in Java is also one of the implementation of the Set interface. Actually LinkedHashSet class in Java extends the HashSet class and uses methods of that class for its operations.

Just like other implementations of the Set interface HashSet and TreeSet, LinkedHashSet also stores unique elements. How LinkedHashSet differs from the HashSet in Java is that it maintains the insertion-order of the elements; that is elements in the LinkedHashSet are stored in the sequence in which they are inserted. Note that insertion order is not affected if an element is re-inserted into the set.


How is LinkedHashSet implemented in Java

LinkedHashSet is the Hash table and linked list implementation of the Set interface, with predictable iteration order. This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries.

If you have idea about how HashSet works internally in Java, you must be knowing internally HashSet uses HashMap for storing its elements. Same way LinkedHashSet class in Java internally uses LinkedHashMap and calls the methods of HashSet class for all the operations.

Some of the important points about LinkedHashSet in Java are as follows-

  • LinkedHashSet is an ordered set and maintains the insertion order of its elements.
  • LinkedHashSet only stores unique elements, no duplicates.
  • LinkedHashSet permits one null element to be added.
  • LinkedHashSet implementation is not synchronized hence not thread safe. If LinkedHashSet is to be used in a multi-threaded environment where it is accessed and modified concurrently then it must be synchronized externally. That can be done by wrapping the set with in Collections.synchronizedSet method.
  • The iterators returned by LinkedHashSet's iterator method are fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the Iterator throws a ConcurrentModificationException.

Java LinkedHashSet Constructors

  • LinkedHashSet()- Constructs a new, empty linked hash set with the default initial capacity (16) and load factor (0.75).
  • LinkedHashSet(int initialCapacity)- Constructs a new, empty linked hash set with the specified initial capacity and the default load factor (0.75).
  • LinkedHashSet(int initialCapacity, float loadFactor)- Constructs a new, empty linked hash set with the specified initial capacity and load factor.
  • LinkedHashSet(Collection<? extends E> c)- Constructs a new linked hash set with the same elements as the specified collection.

Just take any of the Constructor of the LinkedHashSet and you will see all those constructors will ultimately call the Constructor of the HashSet where map will be initialized as a LinkedHashMap.

For example if we take the following constructor of the LinkedHashSet-
public LinkedHashSet(int initialCapacity, float loadFactor) {
  super(initialCapacity, loadFactor, true);
}

Which in turn calls a constructor in HashSet and instantiates a LinkedHashMap-

HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

LinkedHashSet creation Java example

Following example shows how to create a LinkedHashSet and add elements to it.

public class LinkedHSDemo {

  public static void main(String[] args) {
    // Using Diamond operator Which is available from Java 7
    // Use LinkedHashSet<String> if using less than version 7
    Set<String> citySet = new LinkedHashSet<>();
    
    citySet.add("Delhi");
    citySet.add("Mumbai");
    citySet.add(null);
    citySet.add("Bangalore");
    citySet.add("Delhi");
    citySet.add(null);
    
    // Iterating the Set
    for(String str : citySet){
      System.out.println("" + str);
    }     
  }
}

Output

Delhi
Mumbai
null
Bangalore

Points to note here-

  • It can be seen that the insertion order is maintained. While iterating the LinkedHashSet elements are displayed in the order they were inserted.
  • Even though Delhi is inserted twice it is displayed only once which shows that the LinkedHashSet doesn't allow duplicates and insertion order is not affected if an element is re-inserted into the set.
  • Only one null is allowed in the LinkedHashSet, even if I have tried to insert null twice it can be seen that only one is stored.

LinkedHashSet element removal example

public class LinkedHSDemo {

  public static void main(String[] args) {
    Set<String> citySet = new LinkedHashSet<String>();
    // Adding elements
    citySet.add("London");        
    citySet.add("Tokyo");
    citySet.add("New Delhi");
    citySet.add("Beijing");
    citySet.add("Nairobi");
    // checking of set contains that element
    if(citySet.contains("Nairobi")) {
      citySet.remove("Nairobi");
    }
    System.out.println("--LinkedHashSet after removing using remove method--");
    for(String city : citySet){
      System.out.println("City- " + city);        
    }
    //using removeIf method
    citySet.removeIf((String city)->city.equalsIgnoreCase("Tokyo"));
    
    System.out.println("--LinkedHashSet after removing using removeIf method--");
    for(String city : citySet){
      System.out.println("City- " + city);        
    }    
    System.out.println("Total number of elements in LinkedHashSet- " + citySet.size()); 
  }
}

Output

--LinkedHashSet after removing using remove method--
City- London
City- Tokyo
City- New Delhi
City- Beijing
--LinkedHashSet after removing using removeIf method--
City- London
City- New Delhi
City- Beijing
Total number of elements in LinkedHashSet- 3

LinkedHashSet is not synchronized

LinkedHashSet in Java is not thread safe. In case we need to Synchronize it, it should be synchronized externally. That can be done using the Collections.synchronizedSet() method.

Set s = Collections.synchronizedSet(new LinkedHashSet(...));

LinkedHashSet class' iterator is fail-fast

Iterator returned by LinkedHashSet is fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException.

Performance of LinkedHashSet in Java

The performance of LinkedHashSet is likely to be just slightly below that of HashSet, due to the added expense of maintaining the linked list. But there is one exception: Iteration over a LinkedHashSet requires time proportional to the size of the set, regardless of its capacity. Iteration over a HashSet is likely to be more expensive, requiring time proportional to its capacity as in the case of HashSet based on the Hashing function it may have to go through all the buckets .

That's all for this topic LinkedHashSet in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How HashSet Works Internally in Java
  2. TreeSet in Java With Examples
  3. EnumSet in Java With Examples
  4. How to Sort Elements in Different Order in TreeSet
  5. Java Collections Interview Questions And Answers

You may also like-

  1. How to Sort ArrayList of Custom Objects in Java
  2. Difference Between Comparable and Comparator in Java
  3. Difference Between ArrayList And LinkedList in Java
  4. How to Create Immutable Class in Java
  5. Interface Static Methods in Java
  6. Lambda Expression Examples in Java
  7. Why wait(), notify() And notifyAll() Must be Called Inside a Synchronized Method or Block
  8. Varargs (Variable-length Arguments) in Java

Friday, September 10, 2021

How to Sort Elements in Different Order in Java TreeSet

By default elements in TreeSet are sorted using natural ordering of the elements. If you want to sort a TreeSet in Java using different order than the natural order like in descending order or reverse order then you need to provide your own Comparator at Set creation time.

Let's see a Java example where TreeSet is sorted in descending order rather than the natural ordering (which is ascending in case of String).

public class TreeSetDemo {
  public static void main(String[] args) {
    // Providing custom compartor
    Set<String> citySet = new TreeSet<String>(
      new CityComparator());
    
    citySet.add("Delhi");
    citySet.add("Mumbai");
    citySet.add("Bangalore");
    citySet.add("Chennai");
    citySet.add("Hyderabad");
    
    // Iterating the Set
    for(String str : citySet){
      System.out.println("City Name - " + str);
    }
  }
}

// Comparator class
class CityComparator implements Comparator<String>{
  @Override
  public int compare(String str1, String str2) {
    return str2.compareTo(str1);
  }    
}

Output

City Name - Mumbai
City Name - Hyderabad
City Name - Delhi
City Name - Chennai
City Name - Bangalore

Here note that a Comparator implementation is provided which reverses the sorting order. That Comparator is specified at the set creation time in a constructor.

That's all for this topic How to Sort Elements in Different Order in Java TreeSet. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. How to Iterate a HashMap of ArrayLists of String in Java
  2. How to Sort ArrayList in Java
  3. How to Sort ArrayList of Custom Objects in Java
  4. Count Number of Times Each Character Appears in a String Java Program
  5. Difference Between Comparable and Comparator in Java

You may also like-

  1. Convert String to double in Java
  2. Compress And Decompress File Using GZIP Format in Java
  3. Remove Duplicate Elements From an Array in Java
  4. LinkedHashSet in Java With Examples
  5. Synchronization in Java - Synchronized Method And Block
  6. Difference Between Checked And Unchecked Exceptions in Java
  7. Polymorphism in Java
  8. Dependency Injection in Spring Framework

Sunday, August 29, 2021

HashSet in Java With Examples

HashSet in Java is the implementation of the Set interface and it is an unordered collection meaning insertion order is not maintained in a HashSet.

Following are the important points about the HashSet in Java.
  1. HashSet is part of Java Collections framework. HashSet class extends AbstractSet and implements Set, Cloneable and Serializable interfaces.
  2. HashSet is an unordered collection. A hash is calculated using the element that is added to the HashSet and that decides where the element will be stored.
  3. HashSet only stores unique elements, meaning duplicates are nor allowed.
  4. HashSet permits one null element to be added.
  5. HashSet implementation is not synchronized hence not thread safe. If HashSet is to be used in a multi-threaded environment where it is accessed and modified concurrently then it must be synchronized externally. That can be done by wrapping the set with in Collections.synchronizedSet method.
  6. The iterators returned by HashSet's iterator method are fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the Iterator throws a ConcurrentModificationException.

Sunday, August 15, 2021

HashSet Vs LinkedHashSet Vs TreeSet in Java

Though HashSet, LinkedHashSet and TreeSet all are implementation of the Set interface and share some traits like storing only the unique elements, not being thread-safe but there are certain differences too related to performance, how elements are ordered etc. So it is very important to know these differences among HashSet, LinkedHashSet and TreeSet in Java as it will help you to make an informed choice which Set implementation to use to meet the requirement.

HashSet Vs LinkedHashSet Vs TreeSet in Java

  1. First and most important difference is related to the ordering of the elements.
    HashSet is unordered, it will store elements on the basis of the calculated hash that's it.
    LinkedHashSet maintains the insertion ordering of the elements.
    TreeSet keeps the element in sorted order. The sorting orders TreeSet follows by default is the natural ordering of the elements.

  2. Another difference is related to allowing null value.
    HashSet as well as LinkedHashSet allow null value to be stored. Mind you only one null value is allowed in both HashSet and LinkedHashSet.
    TreeSet does not allow null value, trying to add null to a TreeSet will result in a null pointer exception.

  3. For HashSet and LinkedHashSet comparison of the elements is done using equals() method. Note that set allows only unique elements, and that uniqueness is maintained by using the equals() method to compare elements.
    TreeSet does the comparison of the element using the compareTo (or compare) method, depending on whether sorting is done using Comparable or Comparator.
  4. Performance wise HashSet is at the top as it has no added baggage of insertion ordering or sorting. If hashing is done correctly HashSet offers constant time performance O(1) for the basic operations (add, remove, contains and size). As I mentioned this performance is assuming that the hash function disperses the elements properly among the buckets. If HashCode is not proper the performance may degrade and in worst case it will be O(n).
    For LinkedHashSet performance is likely to be just slightly below that of HashSet, due to the added expense of maintaining the linked list.
    TreeSet has to sort elements with every insertion so that way performance is slow, but TreeSet provides guaranteed log(n) time cost for the basic operations (add, remove and contains) irrespective of the number of elements stored.

That's all for this topic HashSet Vs LinkedHashSet Vs TreeSet in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How HashSet Works Internally in Java
  2. EnumSet in Java With Examples
  3. How to Sort Elements in Different Order in TreeSet
  4. Difference Between ArrayList And LinkedList in Java
  5. Java Collections Interview Questions And Answers

You may also like-

  1. Difference Between Comparable and Comparator in Java
  2. Java ReentrantLock With Examples
  3. Lambda expression examples in Java 8
  4. Spliterator in Java
  5. finalize method in Java
  6. super Keyword in Java With Examples
  7. Multi-Catch Statement in Java Exception Handling
  8. Why wait(), notify() and notifyAll() must be called inside a synchronized method or block?

Friday, August 13, 2021

How to Loop Through HashSet in Java

In this post we’ll see how you can iterate any Set implementation like HashSet in Java. To loop through a HashSet you have following options, you can choose based on your requirement or the Java version you are using.

  1. First option to iterate a HashSet in Java is to use a ForEach loop, if you are just iterating without doing any structural modification (adding or removing element) to the Set then this is the best option to iterate a HashSet.
  2. Using iterator() method which returns an iterator over the elements in the given Set. If you have to remove any element while iterating then use this option otherwise ConcurrentModificationException will be thrown.
  3. Java 8 onwards you also have an option to use forEach statement to iterate a HashSet in Java.

Iterating a HashSet – Java example

Let’s see a Java example code which illustrates all of the options mentioned above to loop through a HashSet.

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

public class IterateSetDemo {

  public static void main(String[] args) {
    // creating a HashSet
    Set<String> citySet = new HashSet<String>();
    // Adding elements
    citySet.add("London");        
    citySet.add("Tokyo");
    citySet.add("New Delhi");
    citySet.add("Beijing");
    citySet.add("Nairobi");
    
    System.out.println("-- Iterating HashSet - ForEach loop --");
    for(String city : citySet){
      System.out.println("city- " + city);
    }
    
    System.out.println("-- Iterating HashSet - using iterator --");
    Iterator<String> itr = citySet.iterator();
    while(itr.hasNext()){            
      System.out.println("city- " + itr.next());        
    }
    
    System.out.println("-- Iterating HashSet - using forEach statement-- ");
    citySet.forEach((city)->System.out.println("city- " + city));        
  }
}

Output

-- Iterating HashSet - ForEach loop --
city- Beijing
city- New Delhi
city- Nairobi
city- Tokyo
city- London
-- Iterating HashSet - using iterator --
city- Beijing
city- New Delhi
city- Nairobi
city- Tokyo
city- London
-- Iterating HashSet - using forEach statement-- 
city- Beijing
city- New Delhi
city- Nairobi
city- Tokyo
city- London

That's all for this topic How to Loop Through HashSet in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How to Loop Through a Map in Java
  2. How to Sort HashSet in Java
  3. LinkedHashSet in Java With Examples
  4. How ArrayList Works Internally in Java
  5. Java Collections Interview Questions And Answers

You may also like-

  1. Java ReentrantLock With Examples
  2. How and Why to Synchronize ArrayList in Java
  3. CopyOnWriteArrayList in Java With Examples
  4. Executor And ExecutorService in Java With Examples
  5. Array in Java With Examples
  6. instanceof Operator in Java
  7. Comparing Enum to String in Java
  8. Spring NamedParameterJdbcTemplate Insert, Update And Delete Example

Friday, July 2, 2021

How HashSet Works Internally in Java

In this post we'll see how HashSet internally works in Java, which is also a favourite Java Collections interview question but before going into internal implementation of HashSet in Java it is important to know two points about HashSet.

  1. HashSet in Java only stores unique values i.e. no duplicates are allowed.
  2. HashSet works on the concept of hashing just like HashMap in Java but its working differs from the HashMap in the following way-
    • In HashMap a (Key, Value) pair is added and the hash function is calculated using key.
    • Where as in the HashSet hash function is calculated using the value itself. Note that in HashSet we have add(E e) method which takes just the element to be added as parameter.
    Also you may have guessed by now, since hash function is calculated using value that is why only unique values are stored in the HashSet. If you try to store the same element again, the calculated hash function would be same, thus the element will be overwritten.

HashSet internally uses HashMap

Now coming back to internal implementation of HashSet in Java the most important point is HashSet class implementation internally uses HashMap to store it's elements.

Within the HashSet there are many constructors one without any parameter and several more with initial capacity or load factor but each one of these constructor creates a HashMap. Since HashSet internally uses HashMap so knowing how HashMap works internally in Java will help you to understand how HashSet works internally in Java.

HashSet Constructor snippets

In the HashSet class in Java you can see that constructors of the class do create a HashMap.

/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
  map = new HashMap<>();
}
public HashSet(int initialCapacity, float loadFactor) {
  map = new HashMap<>(initialCapacity, loadFactor);
}

And the map, which is used for storing values, is defined as

private transient HashMap<E,Object> map;

In the constructor, if you have noticed, there are parameters named initial capacity and load factor. For HashSet, default initial capacity is 16, that is an array (or bucket) of length 16 would be created and default load factor is 0.75. Where load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased.

How elements are added - HashSet internal implementation

I stated in the point 2 above that HashSet calculates the hash function using value itself and there is no (Key, Value) pair in HashSet and then came the statement that HashSet internally uses HashMap to store objects. These two statements may sound contradictory as HashMap stores (key, value) pair so let's see how these these two contradictory statements hold true.

Actually from add method of HashSet class put() method of HashMap is called where the value, which has to be added in the Set, becomes Key and a constant object "PRESENT" is used as value.

That's how PRESENT is defined in HashSet implementation-

// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

And that's how add method is implemented in HashSet class -

public boolean add(E e) {
  return map.put(e, PRESENT)==null;
} 

So you can see with in the internal implementation of the HashSet it's a (key, value) pair which is actually getting added. It's just that the actual value (which is added to the HashSet) becomes the key and a dummy value "PRESENT" is added as value when storing it in the backing HashMap.

For example a statement for adding an element to HashSet- set.add("Mumbai"); internally translates into map.put("Mumbai", PRESENT); and then added to the backing HashMap instance.

One thing to note here is, in HashMap value may be duplicate but Key should be unique. That's how HashSet makes sure that only unique values are stored in it, since the value which is to be stored in the HashSet becomes the key while storing it in HashMap.

How element is removed - HashSet internal implementation

When we need to remove an element from the HashSet, internally again remove method of HashSet calls remove(Object key) method of the HashMap.

That is how it is implemented in HashSet class.

public boolean remove(Object o) {
  return map.remove(o)==PRESENT;
}

Here note that remove(Object key) method of the HashMap returns the Value associated with the key. Whereas the remove(Object o) method of the HashSet returns Boolean value. Also we know that for every value added in HashSet, internally when it is added to the associated HashMap, value becomes Key and the value is always an object called PRESENT. Therefore the value that is returned from the remove(Object key) method of the HashMap is always PRESENT thus the condition map.remove(o)==PRESENT.

How elements are retrieved from HashSet in Java

In HashSet there is no get method as provided in Map or List. In HashSet iterator is there which will iterate through the values of the Set. Internally it will call the keyset of the HashMap, as values are stored as keys in the HashMap so what we'll get is the values stored in the HashSet.

That's how iterator is internally implemented in the HashSet in Java.

/**
* Returns an iterator over the elements in this set. The elements
* are returned in no particular order.
*
* @return an Iterator over the elements in this set
* @see ConcurrentModificationException
*/
public Iterator<E> iterator() {
  return map.keySet().iterator();
}

Points to note

  1. Unlike HashMap where hash function is calculated using key HashSet uses the value itself to calculate the hash function.
  2. Since hash function is calculated using value that is why only unique values are stored in the HashSet.
  3. HashSet internally uses HashMap to store its elements.
  4. When element is added to HashSet using add(E e) method internally HashSet calls put() method of the HashMap where the value passed in the add method becomes key in the put() method. A dummy value “PRESENT” is passed as value in the put() method.

Recommendations for learning (Udemy Courses)

  1. Java Programming Masterclass Course
  2. Java In-Depth: Become a Complete Java Engineer!
  3. Spring Framework Master Class Course
  4. Complete Python Bootcamp Course
  5. Python for Data Science and Machine Learning

That's all for this topic How HashSet Works Internally in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How ArrayList Works Internally in Java
  2. How HashMap Works Internally in Java
  3. How LinkedList Class Works Internally in Java
  4. LinkedHashSet in Java With Examples
  5. TreeSet in Java With Examples

You may also like-

  1. EnumSet in Java With Examples
  2. Java Collections Interview Questions And Answers
  3. Varargs (Variable-length Arguments) in Java
  4. finalize method in Java
  5. Interface Static Methods in Java
  6. Method Reference in Java
  7. String Vs StringBuffer Vs StringBuilder in Java
  8. Why wait(), notify() And notifyAll() Must be Called Inside a Synchronized Method or Block

Sunday, May 16, 2021

How to Sort HashSet in Java

There may be a situation when you want to sort a HashSet in Java. Since the very idea of HashSet is to store elements according to the calculated Hash so by design HashSet is unordered. Thus, in order to sort a HashSet you can either-

  • Convert HashSet to a list and then sort that List by using Collections.sort() method. One drawback of using this option to sort a HashSet is that you get the result as list.
  • Create a TreeSet by passing the HashSet, it will automatically be sorted. TreeSet is an implementation of SortedSet and stores its element in sorted order. This option gives the result as Set.

Let's see a Java program where a HashSet storing strings is sorted.

Java Program to sort a HashSet

public class SetSorting {

  public static void main(String[] args){
    Set<String> citySet = new HashSet<String>();
    citySet.add("Delhi");
    citySet.add("Mumbai");
    citySet.add("Bangalore");
    citySet.add("Chennai");
    citySet.add("Hyderabad");
    
    //Convert it to a list and sort
    List<String> cityList = new ArrayList<>(citySet);
    Collections.sort(cityList);
    System.out.println("Sorted List " + cityList);
    
    // Sorting HashSet by using treeset
    Set<String> sortedSet = new TreeSet<String>(citySet);
    System.out.println("Sorting set by converting it to TreeSet " + sortedSet);
    
    // By using Java 8 stream and sorting
    Set<String> ab = citySet.stream().collect(Collectors.toCollection(TreeSet::new));
    System.out.println("SOrted Set using Java 8 Stream " + ab);
  }
}

Output

Sorted List [Bangalore, Chennai, Delhi, Hyderabad, Mumbai]
Sorting set by converting it to TreeSet [Bangalore, Chennai, Delhi, Hyderabad, Mumbai]
SOrted Set using Java 8 Stream [Bangalore, Chennai, Delhi, Hyderabad, Mumbai]

Here first way to sort HashSet is to convert HashSet into a List and then sort that list. If you are ok with having a sorted elements in a list then this way is just fine. But don't do the mistake of converting it back to HashSet as shown below because converting back to HashSet will again make it unordered.

citySet = new HashSet<String>(cityList);
System.out.println("" + citySet);

While sorting a HashSet using a TreeSet, if you want another ordering than the natural ordering then you'll have to provide a comparator with the treeset.

From Java 8 onwards sorting the HashSet using a TreeSet can be done using collect() operation in stream API. It is still creating a TreeSet using the given HashSet but method reference is used here to create a new TreeSet.

That's all for this topic How to Sort HashSet in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How HashSet Works Internally in Java
  2. LinkedHashSet in Java With Examples
  3. How to Sort ArrayList of Custom Objects in Java
  4. Difference Between Comparable and Comparator in Java
  5. Java Collections Interview Questions And Answers

You may also like-

  1. How to Remove Duplicate Elements From an ArrayList in Java
  2. CopyOnWriteArraySet in Java With Examples
  3. finalize method in Java
  4. Varargs (Variable-length Arguments) in Java
  5. Why wait(), notify() and notifyAll() must be called inside a synchronized method or block?
  6. Java ThreadLocal Class With Examples
  7. Deadlock in Java Multi-Threading
  8. Java Multithreading Interview Questions And Answers

Tuesday, April 20, 2021

EnumSet in Java With Examples

EnumSet in Java is a specialized set implementation for use with enum types. EnumSet was introduced in Java 5 along with the Enum. All of the elements stored in an EnumSet must, explicitly or implicitly, come from a single enum type that is specified while creating the set. All basic operations of the EnumSet execute in constant time. They are likely (though not guaranteed) to be much faster than their HashSet counterparts.

According to Java docs "Enum sets are represented internally as bit vectors. This representation is extremely compact and efficient. The space and time performance of this class should be good enough to allow its use as a high-quality, typesafe alternative to traditional int-based "bit flags." Even bulk operations (such as containsAll and retainAll) should run very quickly if their argument is also an enum set."

How EnumSet works in Java

One of the things to note about EnumSet is that it is an abstract class and uses factory methods to create objects. There are two concrete implementations of EnumSet in Java-

  • RegularEnumSet- Private implementation class for EnumSet, for "regular sized" enum types
  • JumboEnumSet- Private implementation class for EnumSet, for "jumbo" enum types (i.e., those with more than 64 elements).
Both of these classes can't be instantiated directly by the user as these classes have default (package-private) access.

Depending upon the size of the Enum any of these classes is instantiated by the EnumSet class itself. If Enum has 64 or fewer enum constants then RegularEnumSet is used otherwise JumboEnumSet.

Tuesday, March 16, 2021

TreeSet in Java With Examples

TreeSet in Java is also one of the implementation of the Set interface like HashSet and LinkedHashSet. TreeSet implements the NavigableSet interface and extends the AbstractSet class.

Just like other implementations of the Set interface HashSet and LinkedHashSet, TreeSet also stores unique elements. How TreeSet in Java differs from other Set implementations is that TreeSet stores its elements in sorted order. The elements are ordered using their natural ordering or a comparator can be provided at set creation time to provide custom ordering (We'll see an example a little later).


How TreeSet is implemented in Java

TreeSet in Java uses a tree data structure to store its elements thus providing guaranteed log(n) time cost for the basic operations (add, remove and contains).

As we have seen while discussing HashSet and LinkedHashSet internally these implementations use their map counterparts i.e. HashMap and LinkedHashMap respectively. Same way TreeSet also uses TreeMap internally to store its elements.

Sunday, December 6, 2020

CopyOnWriteArraySet in Java With Examples

In Java 5 many concurrent collection classes are added as a thread safe alternative for their normal collection counterparts which are not thread safe. Like ConcurrentHashMap as a thread safe alternative for HashMap, CopyOnWriteArrayList as a thread safe alternative for ArrayList. Same way CopyOnWriteArraySet in Java is added as a thread safe alternative for HashSet in Java.

CopyOnWriteArraySet class in Java

CopyOnWriteArraySet implements the Set interface (Actually it extends the AbstractSet class which in turn implements the set interface). Since CopyOnWriteArraySet implements the Set interface so basic functionality of the Set that only unique elements can be added applies to CopyOnWriteArraySet too.