64

I can think of two ways:

public static IntStream foo(List<Integer> list)
{
    return list.stream().mapToInt(Integer::valueOf);
}

public static IntStream bar(List<Integer> list)
{
    return list.stream().mapToInt(x -> x);
}

What is the idiomatic way? Maybe there is already a library function that does exactly what I want?

Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • Another possible way could be to [use `flatMapToInt` along with `Instream.of`](https://stackoverflow.com/a/53878820/1746118) – Naman Dec 21 '18 at 03:30
  • Using `Integer::valueOf` is hilariously inefficient. I wonder how often things like that occur in production code. I've seen the odd less egregious examples of boxing-unboxing. – Tom Hawtin - tackline Nov 07 '22 at 10:05

2 Answers2

68

I guess (or at least it is an alternative) this way is more performant:

public static IntStream baz(List<Integer> list)
{
    return list.stream().mapToInt(Integer::intValue);
}

since the function Integer::intValue is fully compatible with ToIntFunction since it takes an Integer and it returns an int. No autoboxing is performed.

I was also looking for an equivalent of Function::identity, i hoped to write an equivalent of your bar method :

public static IntStream qux(List<Integer> list)
{
    return list.stream().mapToInt(IntFunction::identity);
}

but they didn't provide this identity method. Don't know why.

gontard
  • 28,720
  • 11
  • 94
  • 117
  • 3
    lol, I confused `Integer::valueOf` with `Integer::intValue`. My proposed function `foo` unboxes the Integer in the list to pass it into `valueOf`, then it gets returned in a box, and then it is unboxed *again* to be put into the stream :) – fredoverflow Jul 08 '14 at 15:01
  • Why would `Integer::intValue` be more performant than `x -> x`? – shmosel Mar 04 '16 at 05:57
  • 1
    @shmosel because no autoboxing is performed by `intValue` – gontard Mar 09 '16 at 08:48
  • 5
    What autoboxing? In the lambda version, x is already an Integer (from the List), and "return x" implicitly _un_boxes it to an int, using intValue. I suspect that the difference would start out imperceptibly small, and get smaller by the time the JIT is through with it. – yshavit Mar 09 '16 at 08:59
  • 1
    @yshavit not to mention that an identity function would do the exact same thing as well. – shmosel Mar 09 '16 at 09:19
  • @yshavit the boxing that happens when the Integer value is passed to the applyAsInt() method which accepts an object reference and is returned as an int, then boxed back to Integer again to be a part of the IntStream, I guess. – Victor Zamanian Jul 14 '16 at 23:28
  • 1
    @VictorZamanian - there is no boxing there. The value starts out as `Integer` in the list, and is passed to `ToIntFunction.applyAsInt(T value)`, which accepts an object and returns `int` so there is no boxing to convert `Integer` to `T` while calling that. Then the lambda function `x -> x` takes an `Integer x` and returns it, meaning it is unboxed to conform to the `int` return type. There is no futher boxing or unboxing. A valid reason to prefer `Integer::intValue` is that no additional lambda function is created - the method reference can be used directly. – BeeOnRope Apr 17 '17 at 20:08
  • @BeeOnRope, you're right -- I was thinking of `IntStream` as a stream of `Integer`, not of `int`. My mistake. – Victor Zamanian Apr 18 '17 at 10:29
  • 1
    @gontard Do you want to say that explicit unboxing is faster than implicit? – cofirazak Mar 14 '20 at 11:19
7

An alternate way to transform that would be using Stream.flatMapToInt and IntStream.of as:

public static IntStream foobar(List<Integer> list) {
    return list.stream().flatMapToInt(IntStream::of);
}

Note: Went through few linked questions before posting here and I just couldn't find this suggested in them either.

Naman
  • 27,789
  • 26
  • 218
  • 353