Pull to refresh

Comments 8

Что вы имеете в виду? Приведите пример желаемого кода и желаемый эффект от него.

// { 1 = (1, 3), 0 = (2, 4) }
Seq.of(1, 2, 3, 4).groupBy(i -> i % 2);

// (tuple(1, (1, 3)), tuple(0, (2, 4)))
Seq.of(1, 2, 3, 4).grouped(i -> i % 2);

из jOOλ

А, вы хотите шорткат к Stream.of(1, 2, 3, 4).collect(groupingBy(i -> i % 2))? Нет, не будет, конечно. Стандартная библиотека выдерживается в минималистичном виде и экономию десятка символов уж точно никто не оправдает. В StreamEx у меня есть аналогичный шорткат (StreamEx.of(1, 2, 3, 4).groupingBy(i -> i % 2)).


Ну а туплов в Java вроде и не планируется, соответственно аналога grouped точно не ждите. Можно сделать Stream.of(1, 2, 3, 4).collect(groupingBy(i -> i % 2)).entrySet().stream() — эффект аналогичный (получите Stream<Entry<Integer, Integer>>). Можете принимать Entry за тупл.

UFO just landed and posted this here

Если вы будете складывать с помощью Stream API подряд идущие числа, то можете потерять в скорости по сравнению с циклом раз в 10-15. Хотя зачем всё это, если можно воспользоваться формулой n*(n+1)/2, которая будет гораздо быстрее цикла.


Если вы делаете хоть что-то нетривиальное (хотя бы строки конкатенируете), то накладные расходы от стримов редко замедляют процесс вдвое. Для существенной части бизнес-логики вы не потеряете более 10-30%. Если у вас в соседней строке выполняется SQL-запрос, то вам должно быть совершенно наплевать на оверхед от стримов.


Боксингов там обычно нет, если правильно пользоваться стримами. Чаще всего дополнительных поэлементных выделений памяти вообще нет по сравнению с аналогичным циклом. Виртуальные вызовы есть, это проблема, из-за них основной оверхед и происходит.

Вот, кстати, простенький бенчмарк, который показывает, что я даже недооцениваю стримы.


# JMH 1.13 (released 27 days ago)
# VM version: JDK 1.8.0_91, VM 25.91-b14
# VM invoker: C:\Program Files\Java\jre1.8.0_91\bin\java.exe
Benchmark         (n)  (pollute)  Mode  Cnt     Score     Error  Units
Concat.stream      10       true  avgt   15     0,335 ±   0,008  us/op
Concat.stream      10      false  avgt   15     0,312 ±   0,006  us/op
Concat.stream    1000       true  avgt   15    26,733 ±   0,740  us/op
Concat.stream    1000      false  avgt   15    24,910 ±   0,477  us/op
Concat.stream  100000       true  avgt   15  3127,121 ± 299,316  us/op
Concat.stream  100000      false  avgt   15  2869,882 ±  86,572  us/op
Concat.plain       10       true  avgt   15     0,254 ±   0,011  us/op
Concat.plain       10      false  avgt   15     0,258 ±   0,013  us/op
Concat.plain     1000       true  avgt   15    25,366 ±   0,438  us/op
Concat.plain     1000      false  avgt   15    24,992 ±   0,705  us/op
Concat.plain   100000       true  avgt   15  2829,553 ± 162,468  us/op
Concat.plain   100000      false  avgt   15  2762,287 ± 122,223  us/op

С грязным профилем типов конкатенация 10 строчек проседает на 30% при использовании стримов, а конкатенация 1000 и 100000 строчек — всего процентов на 7-10. Причём строки короткие. Длинные медленнее конкатенируются и разница будет меньше. Я детально не вникал, но разница, вероятно, как раз из-за виртуальных вызовов, потому что на чистом профиле производительность вообще одинаковая для 1000 и 100000 строчек.


В общем, стоит задумываться, если у вас большое количество мелких стримов. А так провал в производительности не должен вас беспокоить. Стандартное правило — оптимизируйте то, что тормозит. Стримы можно использовать почти повсеместно в бизнес-логике. Самое медленное место вряд ли окажется именно в стримах.

Стандартное правило — оптимизируйте то, что тормозит.

И к нему ещё одно: тормозные места ищите профайлером, а не шестым чувством.

Sign up to leave a comment.