Почему Iterable & lt; & gt; поскольку тип возврата не может использоваться с .collect (Collectors.toList () [duplicate]

select t3.name, sum(t3.prod_A) as Prod_A, sum(t3.prod_B) as Prod_B, sum(t3.prod_C) as    Prod_C, sum(t3.prod_D) as Prod_D, sum(t3.prod_E) as Prod_E  
from
(select t2.name as name, 
case when t2.prodid = 1 then t2.counts
else 0 end  prod_A, 

case when t2.prodid = 2 then t2.counts
else 0 end prod_B,

case when t2.prodid = 3 then t2.counts
else 0 end prod_C,

case when t2.prodid = 4 then t2.counts
else 0 end prod_D, 

case when t2.prodid = "5" then t2.counts
else 0 end prod_E

from 
(SELECT partners.name as name, sales.products_id as prodid, count(products.name) as counts
FROM test.sales left outer join test.partners on sales.partners_id = partners.id
left outer join test.products on sales.products_id = products.id 
where sales.partners_id = partners.id and sales.products_id = products.id group by partners.name, prodid) t2) t3

group by t3.name ;
334
задан Stuart Marks 3 April 2015 в 14:23
поделиться

9 ответов

Ответ гораздо лучше, чем использование spliteratorUnknownSize напрямую, что также легче и дает лучший результат. Iterable имеет метод spliterator(), поэтому вы должны просто использовать его для получения вашего разделителя. В худшем случае тот же код (реализация по умолчанию использует spliteratorUnknownSize), но в более общем случае, когда ваш Iterable уже является коллекцией, вы получите лучший разделитель и, следовательно, лучшую производительность потока ( возможно, даже хороший параллелизм.) Его также меньше кода:

StreamSupport.stream(iterable.spliterator(), false)
             .filter(...)
             .moreStreamOps(...);

Как вы можете видеть, получение потока из Iterable (см. Почему Iterable & lt; T & gt; не предоставляет поток () и parallelStream ()? ) не очень болезненна.

458
ответ дан Community 21 August 2018 в 01:17
поделиться
  • 1
    Статический метод на Stream был бы приятным, например. Stream.ofIterable(iterable). – robinst 27 August 2015 в 05:35
  • 2
    @robinst Это не было упущением; это был преднамеренный (и очень спорный) выбор. Проблема в том, что если бы это существовало, просто было бы легко достичь этого, не понимая компромиссов, которые приходят с ним. Поскольку Iterable настолько абстрактен, такой метод приведет к возможному наихудшему потоку (без параллельной поддержки, без информации о размере или характеристик (используется для оптимизации вариантов выполнения)). Принуждение большего количества результатов поиска в улучшенных API-интерфейсах по всей экосистеме. Это было компромиссом «наилучшего для кода XYZ». vs ", что лучше всего для всего кода Java. & quot; – Brian Goetz 24 August 2016 в 15:03
  • 3
    Основываясь на вашем объяснении, мне любопытно, почему мы получили Collection.stream (), но не Iterable.stream (). Похоже, что аргумент опускать Iterable.stream () (или Stream.ofIterable ()) применим в равной степени к Collection.stream (). – qualidafial 4 September 2016 в 20:15
  • 4
  • 5
    @BrianGoetz Похоже, что большинство людей не на уровне, чтобы понять, что вы сказали выше или не заботитесь. они просто хотят написать простой код, вызвав простой API. С другой стороны, эти вещи (параллельные ...) могут быть не важны для большинства ежедневных итерационных операций. – user_3380739 7 December 2016 в 01:27

Так как еще один ответ упоминал, что Guava поддерживает это, используя:

Streams.stream(iterable);

Я хочу подчеркнуть, что реализация делает что-то немного отличное от других предложенных ответов. Если Iterable имеет тип Collection, они бросают его.

public static <T> Stream<T> stream(Iterable<T> iterable) {
  return (iterable instanceof Collection)
    ? ((Collection<T>) iterable).stream()
    : StreamSupport.stream(iterable.spliterator(), false);
}

public static <T> Stream<T> stream(Iterator<T> iterator) {
  return StreamSupport.stream(
    Spliterators.spliteratorUnknownSize(iterator, 0),
    false
  );
}
2
ответ дан Alex 21 August 2018 в 01:17
поделиться

Я создал этот класс:

public class Streams {
    /**
     * Converts Iterable to stream
     */
    public static <T> Stream<T>  streamOf(final Iterable<T> iterable) {
        return toStream(iterable, false);
    }

    /**
     * Converts Iterable to parallel stream
     */
    public static <T> Stream<T> parallelStreamOf(final Iterable<T> iterable) {
        return toStream(iterable, true);
    }

    private static <T> Stream<T> toStream(final Iterable<T> iterable, final boolean isParallel) {
        return StreamSupport.stream(iterable.spliterator(), isParallel);
    }
}

Я думаю, что он отлично читается, потому что вам не нужно думать о spliterators и booleans (isParallel).

3
ответ дан g-t 21 August 2018 в 01:17
поделиться

Если вы используете Vavr (ранее известный как Javaslang), это может быть так же просто, как:

Iterable i = //...
Stream.ofAll(i);
0
ответ дан Grzegorz Piwowarek 21 August 2018 в 01:17
поделиться

Если вы можете использовать библиотеку Guava, начиная с версии 21, вы можете использовать

Streams.stream(iterable)
46
ответ дан numéro6 21 August 2018 в 01:17
поделиться
  • 1
    Или, если вы застряли в более старой версии, используйте Lists.newArrayList(Iterable). – Jacob van Lingen 3 February 2017 в 15:06
  • 2
    @JacobvanLingen Это создаст новый список из итерируемого (1 обход + память). – Cogman 1 March 2017 в 00:04

Очень простая работа для этой проблемы заключается в создании интерфейса Streamable<T>, расширяющего Iterable<T>, который содержит метод default <T> stream().

interface Streamable<T> extends Iterable<T> {
    default Stream<T> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
}

Теперь любой из ваших Iterable<T> s могут быть тривиально сделаны потоковыми, просто объявив их implements Streamable<T> вместо Iterable<T>.

2
ответ дан OldCurmudgeon 21 August 2018 в 01:17
поделиться

Я хотел бы предложить использовать библиотеку JOOL , она скрывает магию spliterator за вызовом Seq.seq (iterable), а также предоставляет целую кучу дополнительных полезных функций.

8
ответ дан Shaggie 21 August 2018 в 01:17
поделиться

Вы можете легко создать Stream из Iterable или Iterator:

public static <T> Stream<T> stream(Iterable<T> iterable) {
    return StreamSupport.stream(
        Spliterators.spliteratorUnknownSize(
            iterable.iterator(),
            Spliterator.ORDERED
        ),
        false
    );
}
19
ответ дан Victor Stafusa 21 August 2018 в 01:17
поделиться
  • 1
    Да .. но это начинает загромождать мой код. – rayman 29 May 2014 в 12:29
  • 2
    Вы должны написать эту функцию один раз, а затем просто вызвать ее. Почему вызов stream(...) загромождает ваш код? – gexicide 29 May 2014 в 12:42
  • 3
    Хотел сделать это Inline короткое и элегантное .. вы правы, я могу написать эту функцию один раз .. но я забрасываю код (и не добавляю код). в любом случае этот ответ прав, потому что это способ его преобразования. – rayman 29 May 2014 в 12:45
  • 4
    статический импорт указанной функции. короткий и элегантный. (хотя и не обязательно прозрачные) – aepurniet 29 May 2014 в 12:49
0
ответ дан Piotr 31 October 2018 в 20:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: