WedX - журнал о программировании и компьютерных науках

Примитивный поток против потока объектов и фактический бокс, который происходит

Итак, я понимаю, что у вас могут быть потоки объектов, т.е. Stream<T> и специальные примитивные потоки, например. IntStream, DoubleStream и т. д. Одним из преимуществ последнего является отсутствие автоматического бокса.

Кроме того, если мы возьмем IntStream в качестве примера, у него есть специальные операции, такие как фильтр, который принимает IntPredicate.

Мне было интересно, если бы у меня было IntStream против Stream<Integer>, в какой момент вы экономите на боксе, например.

intstream.filter(x -> x >= 50).forEach(x -> System.out.println(x));

vs

stream.filter(x -> x >= 50).forEach(x -> System.out.println(x));

В первом примере я не вижу упаковки или распаковки. Во втором примере где происходит упаковка/распаковка? Потому что, если поток равен Stream<Integer>, а фильтр принимает Predicate<Integer>, тогда, конечно, нет необходимости упаковывать/распаковывать, и то же самое для IntConsumer против Consumer<T>?


Ответы:


1

С Stream<Integer> ваш поток уже упакован. Итак, в зависимости от того, как вы его создали, есть несколько возможностей:

  • У вас есть изначально упакованные значения. Например, у вас было List<Integer> list в качестве входных данных, и вы написали:

    stream = list.stream();
    
  • Вы упаковали свои значения при создании потока. Например, вы создали его так:

    stream = Stream.iterate(1, x -> x+1);
    

    В этом случае первый аргумент упаковывается в Integer.valueOf(1), а распаковка/упаковка также происходит при каждом вызове лямбды (то есть UnaryOperator<Integer>). Таким образом, у вас есть:

    stream = Stream.iterate(Integer.valueOf(1), x -> Integer.valueOf(x.intValue()+1));
    
  • Вы упаковали свой источник явно через промежуточную операцию восходящего потока. Например:

    stream = IntStream.range(0, 1000).boxed();
    

    В этом случае упаковка выполняется внутри операции .boxed() (сокращение от .mapToObj(Integer::valueOf)).

05.02.2016
  • то, что я пытаюсь здесь понять, это то, что если бы у меня был источник, скажем, List‹Integer›, то мне уже пришлось бы упаковать все его элементы. Учитывая это, мне интересно, лучше ли использовать Stream‹Integer› или IntStream для его обработки, поэтому я смотрю на упаковку/распаковку, которая может произойти во время конвейера. Для начала для получения IntStream потребуется распаковать все объекты Integer из списка, но тогда у вас, возможно, больше не будет упаковки/распаковки. Но с Stream‹Integer› я не вижу никакой дальнейшей упаковки, только распаковку. В литературе обычно упоминается частый бокс, хотя 09.02.2016
  • @Tranquility, вам не нужно заботиться об распаковке: это абсолютно дешево (всего одно разыменование). Что дорого, так это упаковка (фактическое выделение объекта в худшем случае). Также обратите внимание, что каждая числовая операция с Integer (сложение, сравнение и т. д.) требует распаковки. 09.02.2016

  • 2

    Распаковка происходит внутри предиката: в stream.filter(x -> x >= 50) Predicate по существу становится (Integer x) -> x.intValue() >= 50, а intValue() является шагом распаковки. Кроме того, System.out.println сам выполняет некоторую распаковку в реализации Integer.toString, которая в конечном итоге вызывается.

    04.02.2016
  • да, это то, о чем я подумал, забыв о боксе, который мог произойти при заполнении источника Stream‹Integer›, нет никакого дальнейшего бокса, но обычно распаковывается для оценки целочисленных элементов во время лямба-выражений? Мне было интересно, если, когда потоковый конвейер передает элемент, чтобы сказать фильтр, входит ли он как int и, следовательно, помещается в Integer, но я сомневаюсь, что это произойдет. Суть в том, что преимущество наличия аргумента IntPredicate заключается не в том, чтобы остановить упаковку, а в том, чтобы избежать распаковки во время лямбда? 09.02.2016
  • Новые материалы

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

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]