Game Instructions

Tap a tile to toggle its color. When a tile changes nearby tiles may change as well. Each move affect multiple tiles. The target is to turn all tiles into yellow in the fewest steps possible.

Press 'j' to show/hide the game. Press 'i' to show/hide the instructions. Press 't' to show/hide the top score table.

Steps: 0

Top Scores

Name Steps
Press J to toggle the game, I to toggle instructions, and T to toggle the top scores

Congratulations!

You solved the puzzle in 0 steps!

Success!

Score submitted successfully!

Error

Failed to submit score. Please try again.

Collectors in Java Streams

Developer working on Computer
The Java Stream API provides a declarative way to process sequences of data. While intermediate operations such as filter(), map(), and sorted() transform a stream, eventually we usually need to produce a result.

One of the most important terminal operations for doing this is collect(). The collect() method is commonly used together with the utility methods provided by the java.util.stream.Collectors class. Collectors allow us to accumulate stream elements into collections, strings, maps, statistics, grouped structures, and many other forms.

What Is a Collector?

A Collector describes how elements from a stream should be accumulated into a final result.

				
					var names = Stream.of("David", "Anna", "Michael") 
                .collect(Collectors.toList());
System.out.println(names);

				
			

The stream contains several elements, while the final result is a single List object containing those elements. This type of operation is called a mutable reduction.

The output is:

				
					[David, Anna, Michael]
				
			

The collect() Method

The Stream interface includes the following commonly used form of collect():

				
					<R, A> R collect(Collector<? super T, A, R> collector)

				
			
The collector defines how the elements should be accumulated. For example:
				
					var result = Stream.of(1, 2, 3, 4, 5)
          .collect(Collectors.toList());
				
			

In this code sample:

  • The stream contains Integer objects.
  • Collectors.toList() creates the collector.
  • collect() performs the accumulation.
  • The result is a List<Integer>.

Choosing the Collection Type

When we need a specific collection implementation, we can use:

				
					Collectors.toCollection()
				
			

The following code sample shows how to collect the elements into a LinkedHashSet object.

				
					public class ToCollectionDemo {

    public static void main(String[] args) {

        var names = List.of(
                "Eilat",
                "Jerusalem",
                "Haifa",
                "Rehovot"
        );

        var result = names.stream()
            .collect(Collectors.toCollection(LinkedHashSet::new));

        System.out.println(result.getClass().getSimpleName());
        System.out.println(result);

    }
}
				
			

The output of this code is:

				
					LinkedHashSet
[Eilat, Jerusalem, Haifa, Rehovot]
				
			

The reduce() vs collect() Methods

Both reduce() and collect() are reduction operations, but they serve different purposes. The reduce() method is primarily intended for combining elements into an immutable value. 

				
					public class ReduceDemo {
    public static void main(String[] args) {

        int sum = Stream.of(10, 20, 30, 40)
                        .reduce(0, Integer::sum);

        System.out.println(sum);
    }
}
				
			

The output of this code is:

				
					100
				
			

The collect() method is designed for mutable reduction, where elements are accumulated into a mutable result container.

				
					public class CollectDemo {
    public static void main(String[] args) {

        List<String> names =
                Stream.of("David", "Sarah", "John")
                        .collect(Collectors.toList());

        System.out.println(names);
    }
}
				
			

The output of this code is:

				
					[David, Sarah, John]
				
			

Collecting into Map

The Collectors.toMap() method creates a map from the stream elements. When you call this method, you should specify how to calculate the keys and values. 

				
					public class ToMapDemo {

    record Developer(int id, String name) {}

    public static void main(String[] args) {

        var developers =
                Stream.of(
                        new Developer(1, "Israel"),
                        new Developer(2, "Canada"),
                        new Developer(3, "Singapore")
                );

        Map<Integer, String> result =
                developers.collect(
                        Collectors.toMap(
                                Developer::id,
                                Developer::name
                        )
                );

        System.out.println(result);
    }
}
				
			

The output is:

				
					{1=Israel, 2=Canada, 3=Singapore}
				
			

Collectors are one of the most powerful parts of the Java Stream API . They allow streams to be transformed into lists, sets, maps, strings, grouped structures, statistics, and many other results without manually managing loops and mutable accumulators.

Share:

Custom Gatherer

Creating a Custom Gatherer in Java

The gatherers allows us to define custom intermediate stream operations with their own state, processing logic, parallel-combination strategy, and finishing behavior. They are especially useful when standard stream operations are not expressive enough.

The CopyOnWriteArrayList Class

Working with CopyOnWriteArrayList in Java

The CopyOnWriteArrayList class is a thread-safe collection designed for cases in which reads are frequent and modifications are relatively rare. Its copy-on-write strategy makes iteration simple and safe, but writes come with an additional cost.

The Beauty of Code

Coding is Art! Developing Code That Works is Simple. Develop Code with Style is a Challenge!

Update cookies preferences