8

I have an array of [5, 6, 7, 3, 9], I would like to change each element from the array substracting by 2, then store the in a Set, so what I did is

Set<Integer> mySet = Arrays.stream(arr1).map(ele -> new Integer(ele - 2)).collect(Collectors.toSet());

but I am getting two exceptions here as

  1. The method collect(Supplier<R>, ObjIntConsumer<R>, BiConsumer<R,R>) in the type IntStream is not applicable for the arguments (Collector<Object,?,Set<Object>>)"
  2. Type mismatch: cannot convert from Collector<Object,capture#1-of ?,Set<Object>> to Supplier<R>

What does those error mean and how can I fix the issue here with Java Stream operation?

salazarin
  • 807
  • 1
  • 8
  • 26
Kev D.
  • 2,832
  • 6
  • 25
  • 40
  • 1
    Dont use `new Integer(...)`, it is deprecated for good reason. Use `Integer.valueOf(...)` instead. – Zabuzard Apr 27 '20 at 06:16
  • 1
    Thank you @Zabuzard, that was a nice hint! – Kev D. Apr 27 '20 at 06:21
  • 1
    Closely related if not duplicate - [How do I convert a Java 8 IntStream to a List?](https://stackoverflow.com/questions/23674624/how-do-i-convert-a-java-8-intstream-to-a-list) – Naman Apr 27 '20 at 06:25
  • @Naman *Very* closely related, but I am not sure if it is a duplicate, because OP doesn't seem to have known that they were working with an `IntStream` – Lino Apr 27 '20 at 06:30
  • @Lino at least the error message reads that explicitly, just some debugging efforts away if I could say so. – Naman Apr 27 '20 at 06:39

3 Answers3

11

It looks like arr1 is an int[] and therefore, Arrays.stream(arr1) returns an IntStream. You can't apply .collect(Collectors.toSet()) on an IntStream.

You can box it to a Stream<Integer>:

Set<Integer> mySet = Arrays.stream(arr1)
                           .boxed()
                           .map(ele -> ele - 2)
                           .collect(Collectors.toSet());

or even simpler:

Set<Integer> mySet = Arrays.stream(arr1)
                           .mapToObj(ele -> ele - 2)
                           .collect(Collectors.toSet());
Eran
  • 374,785
  • 51
  • 663
  • 734
  • yes, you're right, the arr1 is an int[], so does it mean `.boxed().map(ele -> ele - 2)` and `.mapToObj(ele -> ele - 2)` both returns an IntStream? and is `boxed()` only could be applied on `IntStream` to convert into an `Stream`? – Kev D. Apr 27 '20 at 06:24
  • 1
    No, they both return a `Stream`. They are applied on `IntStream`. And yes, `boxed()` converts an `IntStream` to a `Stream`. – Eran Apr 27 '20 at 06:25
7

Arrays.stream(int[]) returns an IntStream. And IntStream does not offer collect() methods that take a Collector.

If you need to use Collectors.toSet(), then you need a Stream<Integer> for it, and you can call mapToObj for that:

Set<Integer> mySet = Arrays.stream(arr1)
                           .mapToObj(ele -> ele - 2)
                           .collect(Collectors.toSet());
ernest_k
  • 42,928
  • 5
  • 50
  • 93
0

If you're open to using a third-party library, you can avoid boxing the int values as Integer using Eclipse Collections IntSet.

int[] array = {5, 6, 7, 3, 9};
IntStream stream = Arrays.stream(array).map(value -> value - 2);
IntSet actual = IntSets.mutable.ofAll(stream);
IntSet expected = IntSets.mutable.of(3, 4, 5, 1, 7);
Assert.assertEquals(expected, actual);

Note: I am a committer for Eclipse Collections.

Donald Raab
  • 6,038
  • 2
  • 33
  • 38