Як я можу отримати останній елемент потоку чи списку в наступному коді?
Де data.careas
знаходиться List<CArea>
:
CArea first = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal).findFirst().get();
CArea last = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal)
.collect(Collectors.toList()).; //how to?
Як бачите, отримати перший елемент, з певним filter
, не важко.
Однак отримання останнього елемента в одноклапнику - справжній біль:
- Здається, я не можу отримати його безпосередньо від
Stream
. (Це має сенс лише для кінцевих потоків) - Крім того , здається , що ви не можете отримати такі речі , як
first()
іlast()
зList
інтерфейсу, який насправді біль.
Я не бачу жодного аргументу щодо не надання a first()
і last()
методу в List
інтерфейсі, оскільки елементи там впорядковані, і більше того розмір відомий.
Але відповідно до оригінальної відповіді: Як отримати останній елемент скінченного Stream
?
Особисто мені це найближче:
int lastIndex = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal)
.mapToInt(c -> data.careas.indexOf(c)).max().getAsInt();
CArea last = data.careas.get(lastIndex);
Однак це передбачає використання indexOf
кожного елемента, що, швидше за все, ви загалом не хочете, оскільки це може погіршити продуктивність.
Stream
API не є повністю порівнянним LINQ
з тим, як обидва зроблені в дуже різній парадигмі. Це не гірше і не краще - це просто різне. І, безумовно, деякі методи відсутні не тому, що розробники оракул некомпетентні або середні :)
Iterables.getLast
що займає Iterable, але оптимізовано для роботиList
. Поглядом домашніх тварин є те, що його немаєgetFirst
.Stream
API взагалі жахливо анальний, опускаючи безліч зручних методів. C # 's LINQ, звичайно, радий надавати.Last()
і навіть.Last(Func<T,Boolean> predicate)
, хоча він також підтримує нескінченні перелічі.