在我的程序中,我有一个植物列表,每个植物都有一个测量(String),day(int),camera(int)和replicate number(int)。我通过使用过滤器获得了所有想要的植物清单:
List<Plant> selectPlants = allPlants.stream().filter(plant -> passesFilters(plant, filters)).collect(Collectors.toList());
我现在要做的是让所有具有相同摄像头,测量值和重复值的植物。并按顺序组合它们。因此,如果我有1,2,3,5天,我会想要找到所有类似的植物,并将值附加到getValues(函数)的一个植物。
我向Plant添加了一个只使用addAll(新工厂值)附加值的方法。
有没有办法这样做而不反复遍历列表来找到类似的植物,然后每天按时间排序然后追加?对于这个问题的可怕措辞,我感到很抱歉。
答案 0 :(得分:7)
虽然Vakh’s answer是正确的,但却不必要地复杂。
通常,实现自己的密钥类的工作不会得到回报。您可以使用List
作为一个键,这意味着由于装箱原始值而产生轻微的开销,但考虑到我们在这里执行像哈希这样的操作,它可以忽略不计。
并不需要使用for
循环进行排序,更糟糕的是,Comparator
的匿名内部类。为什么我们有溪流和lambdas?您可以使用Comparator
之类的lambda来实现(p1,p2) -> p1.getDay()-p2.getDay()
,或者更好的是Comparator.comparing(Plant::getDay)
。
此外,您可以一步完成整个操作。 sort
步骤将创建一个有序流,收集器将维护遭遇顺序,因此您可以使用一个流进行排序和分组:
Map<List<?>, List<Plant>> groupedPlants = allPlants.stream()
.filter(plant -> passesFilters(plant, filters))
.sorted(Comparator.comparing(Plant::getDay))
.collect(Collectors.groupingBy(p ->
Arrays.asList(p.getMeasurement(), p.getCamera(), p.getReplicateNumber())));
就是这样。
答案 1 :(得分:4)
private static class PlantKey {
private String measurement;
private int camera;
private int replicateNumber;
// + constructor, getters, setters and haschode equals
}
Map<PlantKey, List<Plant>> groupedPlants =
allPlants.stream().filter(plant -> passesFilters(plant, filters))
.collect(Collectors.groupBy(p ->
new PlantKey(p.getMeasurement(),
p.getCamera(),
p.getReplicateNumber())));
// order the list
for(List values : groupedPlants.values()) {
Collections.sort(values, new Comparator<Plant>(){
@Override
public int compare(Plant p1, Plant p2) {
return p1.getDay() - p2.getDay();
}
});
}
答案 2 :(得分:1)
我会根据共同特征对它们进行分组,并比较类似的结果。
for(List<Plant> plantGroup : allPlants.stream().collect(Collectors.groupingBy(
p -> p.camera+'/'+p.measurement+'/'+p.replicate)).values()) {
// compare the plants in the same group
}
答案 3 :(得分:1)
有一个名为sorted
的函数可以在stream
selectPlants.stream().sorted(Comparator.comparingInt(i -> i.day)).collect(Collectors.toList());