Представьте себе простой объект с 3 атрибутами:
public class Obj {
boolean toBeAdded;
String type;
int order;
public Obj(boolean toBeAdded, String type, int order) {
this.toBeAdded = toBeAdded;
this.type = type;
this.order = order;
}
public boolean isToBeAdded() {
return toBeAdded;
}
public String getType() {
return type;
}
public int getOrder() {
return order;
}
}
Представьте, что у меня есть список из нескольких Obj
s разных типов:
import java.util.Arrays;
import java.util.List;
public class Utils {
static List<Obj> createA(){
List<Obj> list = Arrays.asList(
new Obj(true, "A", 1),
new Obj(false, "A", 2),
new Obj(true, "A", 3),
new Obj(false, "A", 4)
);
return list;
}
static List<Obj> createB(){
List<Obj> list = Arrays.asList(
new Obj(true, "B", 1),
new Obj(false, "B", 2),
new Obj(true, "B", 3),
new Obj(false, "B", 4)
);
return list;
}
static List<Obj> createC(){
List<Obj> list = Arrays.asList(
new Obj(false, "C", 1),
new Obj(false, "C", 2),
new Obj(true, "C", 3),
new Obj(true, "C", 4)
);
return list;
}
}
Я хочу как-то отфильтровать этот список и иметь последнее Obj
(максимальное значение order
) для каждого type
, которое может быть добавлено (toBeAdded = true
).
В этом примере результатом должен быть список с:
- Obj1: тип 1, порядок 3
- Obj2: тип 2, порядок 3
- Obj3: тип 3, порядок 4
Я знаю, как фильтровать и сортировать, но до сих пор не мог понять, как получить первое в каждом подтипе. Это противоречит правилам Stream
? Поскольку то, что я хочу сделать, это в основном проанализировать N разных подпотоков для N разных type
s?
Вот что я мог сделать до сих пор:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class MainTest {
public static void main(String[] args) {
List<Obj> list = new ArrayList<>();
list.addAll(Utils.createA());
list.addAll(Utils.createB());
list.addAll(Utils.createC());
System.out.println(list);
List<Obj> filteredList = list
.stream()
.filter(Obj::isToBeAdded)
.sorted(Comparator.comparingInt(Obj::getOrder).reversed())
.collect(Collectors.toList());
System.out.println(filteredList);
}
}
Однако это всего лишь делать простую часть - фильтровать и упорядочивать. Мне все еще нужно сделать что-то вроде findFirst()
для каждого type
. Есть ли способ сделать это?
Нужно ли мне создавать 3 разных потока (по одному для каждого типа), а затем объединять списки? Есть ли способ сделать это, не зная, сколько типов у нас будет? Я также читал про collect(Collectors.groupingBy())
, но это создаст разные карты для каждого типа, что мне не нужно.