How to merge set use java stream with one line of code

Viewed 2280

I have two Set like this:

Set<String> set1;
Set<String> set2;

And I want to merge it with

Set<String> s = Stream.of(set1, set2).collect(Collectors.toSet());

and Error like this:

enter image description here

How can I convert Set to a serial of String object with flatMap? Is there any other solution that can accomplish this operation gracefully?

3 Answers

If you insist on using Streams, you can use flatMap to convert your Stream<Set<String>> to a Stream<String>, which can be collected into a Set<String>:

Set<String> s = Stream.of(set1, set2).flatMap(Set::stream).collect(Collectors.toSet());

You can use Stream.concat to merge the stream of two sets and collect as set.

Set<String> s = Stream.concat(set1.stream(), set2.stream()).collect(Collectors.toSet());

There are couple of approach possible -

Concat

Set<String> s = Stream.concat(set1.stream(), set2.stream()).collect(Collectors.toSet());

It's get slightly ugly for more than 2 streams as we have to write

Stream.concat(Stream.concat(set1.stream(), set2.stream()), set3.stream())

Concat could be a problem for deeply concatenated stream. From documentation -

Use caution when constructing streams from repeated concatenation.Accessing an element of a deeply concatenated stream can result in deep call chains, or even StackOverflowException.

Reduce

Reduce can also be used to perform concatenation of stream as -

Set<String> s = Stream.of(set1.stream(), set2.stream()).reduce(Stream::concat)
  .orElseGet(Stream::empty).collect(Collectors.toSet());

Here Stream.reduce() returns optional that's the reason for orElseGet method call. It's also possible to contact multiple set as

Stream.of(set1.stream(), set2.stream(), set2.stream()).reduce(Stream::concat).orElseGet(Stream::empty).collect(Collectors.toSet());

Problem associated with deeply contacted stream applies to reduce as well

Flatmap

Flatmap can be used to get same result as -

 Set<String> s = Stream.of(set1, set2).flatMap(Set::stream).collect(Collectors.toSet());

To concat multiple stream you can use -

Set<String> s = Stream.of(set1, set2, set3).flatMap(Set::stream).collect(Collectors.toSet());

flatmap avoids StackOverflowException.

Related