Как получить IntStream из списка‹Integer›?

Я могу думать о двух способах:

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);
}

Что такое идиоматический способ? Может быть, уже есть библиотечная функция, которая делает именно то, что я хочу?


person fredoverflow    schedule 08.07.2014    source источник
comment
Другим возможным способом может быть использование flatMapToInt вместе с Instream.of   -  person Naman    schedule 21.12.2018


Ответы (2)


Я думаю (или, по крайней мере, это альтернатива), этот способ более эффективен:

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

поскольку функция Integer::intValue полностью совместима с ToIntFunction, так как он принимает Integer и возвращает int. автоупаковка не выполняется.

Я также искал эквивалент Function::identity, я надеялся написать эквивалент вашего метода bar:

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

но они не предоставили этот метод identity. Не знаю почему.

person gontard    schedule 08.07.2014
comment
лол, я перепутал Integer::valueOf с Integer::intValue. Моя предложенная функция foo распаковывает целое число в списке, чтобы передать его в valueOf, затем оно возвращается в поле, а затем распаковывается снова для помещения в поток :) - person fredoverflow; 08.07.2014
comment
Почему Integer::intValue более эффективен, чем x -> x? - person shmosel; 04.03.2016
comment
@shmosel, потому что intValue не выполняет автобоксинг - person gontard; 09.03.2016
comment
Какой автобокс? В лямбда-версии x уже является целым числом (из списка), и return x неявно _un_boxes его в int, используя intValue. Я подозреваю, что разница вначале будет незаметно небольшой и станет меньше к тому времени, когда JIT завершит ее. - person yshavit; 09.03.2016
comment
@yshavit, не говоря уже о том, что функция идентификации будет делать то же самое. - person shmosel; 09.03.2016
comment
@yshavit упаковка, которая происходит, когда значение Integer передается методу applyAsInt(), который принимает ссылку на объект и возвращается как int, а затем снова упаковывается обратно в Integer, чтобы стать частью IntStream, я думаю. - person Victor Zamanian; 15.07.2016
comment
@VictorZamanian - бокса там нет. Значение начинается с Integer в списке и передается в ToIntFunction.applyAsInt(T value), который принимает объект и возвращает int, так что при вызове нет упаковки для преобразования Integer в T. Затем лямбда-функция x -> x принимает Integer x и возвращает его, что означает, что он распакован для соответствия типу возврата int. Дальнейшей упаковки и распаковки нет. Веская причина предпочесть Integer::intValue заключается в том, что не создается дополнительная лямбда-функция — ссылка на метод может использоваться напрямую. - person BeeOnRope; 17.04.2017
comment
@BeeOnRope, вы правы — я думал о IntStream как о потоке Integer, а не int. Виноват. - person Victor Zamanian; 18.04.2017
comment
@gontard Вы хотите сказать, что явная распаковка выполняется быстрее, чем неявная? - person cofirazak; 14.03.2020

Альтернативный способ преобразования — использование Stream.flatMapToInt и IntStream.of как:

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

Примечание. Просмотрел несколько связанных вопросов, прежде чем публиковать здесь, и я просто не смог найти в них этого предложения.

person Naman    schedule 21.12.2018