9

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?

nehacharya
  • 925
  • 1
  • 11
  • 31
Drex
  • 3,346
  • 9
  • 33
  • 58
  • 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! – Drex 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

12

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
  • 387,369
  • 54
  • 702
  • 768
  • 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`? – Drex 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
  • 44,416
  • 5
  • 53
  • 99
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,458
  • 2
  • 36
  • 44