How do I use Set.of() factory method to create a set object?

As with List.of(), in Java 9, the Set.of() factory method can be used to create an unmodifiable set of specified elements.

Here is a simple example:

package org.kodejava.util;

import java.util.Set;

public class SetOfExample {
    public static void main(String[] args) {
        Set<String> names = Set.of("Rosa", "John", "Mary", "Alice");

        for (String name : names) {
            System.out.println(name);
        }
    }
}

Output:

John
Rosa
Alice
Mary

In this example, the Set.of("Rosa", "John", "Mary", "Alice") statement creates an unmodifiable set of strings containing “Rosa”, “John”, “Mary”, and “Alice”. The resulting set is unmodifiable, so attempting to add, update, or remove elements from it will throw an UnsupportedOperationException.

If you try to create a Set by providing a duplicate elements, an IllegalArgumentException will be thrown. A Set is a type of collection container that cannot have duplicate values in it.

Note that the Set.of() method doesn’t accept null values. If you try to insert a null value, it will throw a NullPointerException. If you add a null value using the add() method UnsupportedOperationException will be thrown.

Set.of() is overloaded similarly to List.of(), allowing you to create a set with varying numbers of elements. The below examples demonstrate the use of Set.of() with different numbers of arguments:

Set<String> a = Set.of(); // An empty set
Set<String> b = Set.of("One"); // A set with one element
Set<String> c = Set.of("One", "Two"); // A set with two elements
// ...
Set<String> j = Set.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"); // A set with ten elements

If you need to create a set with more than 10 elements, Set.of() offers an overloaded version that accepts an array or varargs:

Set<String> set = Set.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven");

Remember that sets created with Set.of() are unmodifiable. Attempting to add, remove or change an element in these sets after their creation causes an UnsupportedOperationException.

Also, Set.of() doesn’t allow duplicate or null elements. If you pass duplicate or null values, it will throw IllegalArgumentException and NullPointerException respectively.

How do I use Collectors.toSet() method?

The Collectors.toSet() method is a method from the java.util.stream.Collectors class that provides a Collector able to transform the elements of a stream into a Set.

Here’s an example of using the Collectors.toSet() method:

package org.kodejava.stream;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class CollectorsToSet {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("Apple", "Banana", "Orange", "Apple", "Banana", "Cherry");

        Set<String> uniqueFruits = fruits.stream()
                .collect(Collectors.toSet());

        System.out.println(uniqueFruits);
    }
}

Output:

[Apple, Cherry, Orange, Banana]

In this example, we have a List<String> of fruits, which contains some duplicate elements. When we stream the list and collect it into a Set using Collectors.toSet(), the result is a Set<String> that only includes the unique fruit names, as a Set doesn’t allow duplicate values.

Remember, like collect other terminal operation, it triggers the processing of the data and will return a collection or other specificity defined type. In case of Collectors.toSet(), the result is a Set.

How do I create a generic Set?

In another post of Java Generics you have seen how to create a generic collection using List in this example you will learn how to make a generic Set. Making a Set generic means that we want it to only hold objects of the defined type. We can declare and instantiate a generic Set like the following code.

Set<String> colors = new HashSet<>();

We use the angle brackets to define the type. We need also to define the type in the instantiation part, but using the diamond operator remove the duplicate and Java will infer the type itself. This declaration and instantiation will give you a Set object that holds a reference to String objects. If you tried to ask it to hold other type of object such as Date or Integer you will get a compiled time error.

Set<String> colors = new HashSet<>();
colors.add("Red");
colors.add("Green");
colors.add("Blue");

//colors.add(new Date()); // Compile time error!

The code for adding items to a set is look the same with the old way we code. But again, one thing you will get here for free is that the compiler will check to see if you add the correct type to the Set. If we remove the remark on the last line from the snippet above we will get a compiled time error. Because we are trying to store a Date into a Set of type String.

Now, let see how we can iterate the contents of the Set. First we’ll do it using the Iterator. And here is the code snippet.

Iterator iterator = colors.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

When using a generic Set it will know that the iterator.next() will return a type of String so that you don’t have use the cast operator. Which of course will make you code looks cleaner and more readable. We can also using the for-each loop when iterating the Set as can be seen in the following example.

for (String color : colors) {
    System.out.println(color);
}

How do I inject collections using set element in Spring?

In this example you will see how to use the <set> element to wire a collection property of a bean. We will reuse the bean that we use in the previous example How do I inject collections using list element in Spring?.

The Album bean have a songs property that have a type of java.util.List. The <set> element does not have to be used with java.util.Set. It can be used to wire a java.util.List collection. It just means it cannot contain duplicate values in it, so the collection will only contain a unique values.

Here how we configure our Spring context:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="song1" class="org.kodejava.spring.core.Song">
        <property name="title" value="I Saw Her Standing There" />
        <property name="writer" value="Beatles" />
    </bean>

    <bean id="song2" class="org.kodejava.spring.core.Song">
        <property name="title" value="Misery" />
        <property name="writer" value="Beatles" />
    </bean>

    <bean id="song3" class="org.kodejava.spring.core.Song">
        <property name="title" value="Anna (Go to Him)" />
        <property name="writer" value="Beatles" />
    </bean>


    <bean id="album" class="org.kodejava.spring.core.Album">
        <property name="title" value="Please Please Me" />
        <property name="year" value="1963" />
        <property name="songs">
            <set>
                <ref bean="song1" />
                <ref bean="song1" />
                <ref bean="song1" />
            </set>
        </property>
    </bean>

</beans>

The <set> configuration can bee seen in the album bean configuration. We set the songs property. Within this property element we use the <set> element. And then using the <ref> element we add some bean into the collection.

Create the following code to run it:

package org.kodejava.spring.core;

public class Song {
    private String title;
    private String writer;

    public Song() {
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setWriter(String writer) {
        this.writer = writer;
    }

    @Override
    public String toString() {
        return "Song{" +
                "title='" + title + '\'' +
                ", writer='" + writer + '\'' +
                '}';
    }
}
package org.kodejava.spring.core;

public class Publisher {
    private String name;

    public Publisher() {
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Publisher{" +
                "name=" + name +
                '}';
    }
}
package org.kodejava.spring.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class Album {
    private String title;
    private int year;
    private List<Song> songs = new ArrayList<>();
    private Map<String, Publisher> publisher = new HashMap<>();
    private Properties props = new Properties();

    public Album() {
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public void setSongs(List<Song> songs) {
        this.songs = songs;
    }

    public void setPublisher(Map<String, Publisher> publisher) {
        this.publisher = publisher;
    }

    public void setProps(Properties props) {
        this.props = props;
    }

    @Override
    public String toString() {
        return "Album{" +
                "title='" + title + '\'' +
                ", year=" + year +
                ", songs=" + songs +
                ", publisher=" + publisher +
                ", props=" + props +
                '}';
    }
}
package org.kodejava.spring.core;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DemoSet {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = 
                new ClassPathXmlApplicationContext("collection-set.xml");

        Album album = (Album) context.getBean("album");
        System.out.println("Album = " + album);
        context.close();
    }
}

You’ll see the following output in the screen. As you can see, although we set three beans into the songs property, the Album bean only contain a one song. This is because we use the <set> element to wire the collection. It does not allow duplicate values.

Album = Album{title='Please Please Me', year=1963, songs=[Song{title='I Saw Her Standing There', writer='Beatles'}], publisher={}, props={}}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>5.3.23</version>
    </dependency>
</dependencies>

Maven Central Maven Central Maven Central

How do I convert java.util.Set into Array?

package org.kodejava.util;

import java.util.*;

public class SetToArray {
    public static void main(String[] args) {
        // Create a java.util.Set object and add some integers into the Set.
        Set<Integer> numberSet = new HashSet<>();
        numberSet.add(1);
        numberSet.add(2);
        numberSet.add(3);
        numberSet.add(5);
        numberSet.add(8);

        // Converting a java.util.Set into an array can be done by creating a
        // java.util.List object from the Set and then convert it into an array
        // by calling the toArray() method on the list object.
        List<Integer> numberList = new ArrayList<>(numberSet);
        Integer[] numbers = numberList.toArray(new Integer[0]);

        // Display the content of numbers array.
        for (int i = 0; i < numbers.length; i++) {
            Integer number = numbers[i];
            System.out.print(number + (i < numbers.length - 1 ? ", " : "\n"));
        }

        // Display the content of numbers array using the for-each loop.
        for (Integer number : numbers) {
            System.out.print(number + ", ");
        }
    }
}