2

Let's say I want to calculate the union of 2 sets, set1 and set2, and assign the result to set3. I do not want to change the values of set1 and set2.

I know I can do it like this:

Set<String> set1 = new HashSet<String>(); set1.add("a");
Set<String> set2 = new HashSet<String>(); set2.add("b");

Set<String> set3 = new HashSet<String>(set1); // copy constructor
set3.addAll(set2);

But I was wondering if there is a more direct syntax like:

Set<String> set3 = (new HashSet<String>(set1)).addAll(set2);

or

Set<String> set3 = new HashSet<String>();
set3.addAll(set1).addAll(set2);

The ways I've tried don't work because addAll() returns a boolean, not the result Set object.

wisbucky
  • 33,218
  • 10
  • 150
  • 101

3 Answers3

3

It's not entirely clear what your criteria are, but here's an alternative:

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

If you're using Guava, you can also do this:

Set<String> set3 = Sets.union(set1, set2);

Note that this actually returns a view. Subsequent modifications to the underlying sets will reflect in set3. If you want an immutable copy, you can use ImmutableSet:

Set<String> set3 = new ImmutableSet.Builder<String>()
        .addAll(set1)
        .addAll(set2)
        .build();
shmosel
  • 49,289
  • 6
  • 73
  • 138
3

Another approach would be:

Set<String> set3 = Stream.of(set1, set2)
                         .flatMap(Collection::stream)
                         .collect(Collectors.toSet());
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
1

In Java 8

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

And Java 9

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

Also, there is a trick with anonymous class.
(As @shmosel suggested in comments this is not good solutions)

Set<String> set5 = new HashSet<>() {{
    addAll(set1);
    addAll(set2);
}};
djm.im
  • 3,295
  • 4
  • 30
  • 45
  • #1 is an exact copy of my answer, #2 is a worse version of Aominè's answer, and #3 is just a bad answer. – shmosel May 17 '18 at 22:29
  • @shmosel "and #3 is just a bad answer." I agree for that. – djm.im May 17 '18 at 22:35
  • The reason I posted the third way is because in the question is asked for "a more direct syntax". And I just tried to compile all options. – djm.im May 17 '18 at 22:39
  • You forgot to include this: `Set set3 = ((Supplier>)() -> { Set set = new HashSet<>(); set1.forEach(set::add); set2.forEach(set::add); return set; }).get();` – shmosel May 17 '18 at 22:42
  • If you suggest that I tried to copy you answer. I didn't. I tried all ansers myself. Also, there is similar answer https://stackoverflow.com/a/30139228/2564509 or this source http://www.techiedelight.com/merge-two-sets-java/ . – djm.im May 17 '18 at 22:53
  • I added notes in my answer you suggested. Thank you for that. – djm.im May 17 '18 at 22:54
  • For the last technique, I needed a `String` inside `new HashSet()` – wisbucky May 18 '18 at 20:24
  • @wisbucky Check your compiler level. Since Java 7 there is diamond operator. – djm.im May 19 '18 at 08:48