在我的程序中,我有一个植物列表,每个植物都有一个度量(字符串)、一天(int)、一个照相机(int)和一个复制数(Int)。我通过使用过滤器获得所有需要的植物的列表:
List<Plant> selectPlants = allPlants.stream().filter(plant -> passesFilters(plant, filters)).collect(Collectors.toList());
我现在想做的是,把所有拥有相同相机、测量和复制值的植物都拿出来。把它们按照白天的顺序组合起来。因此,如果我有1,2,3,5天,我希望找到所有类似的植物,并将值附加到getValues (函数)所在的一个工厂。
我只使用addAll(新的工厂值)添加了一个附加值的方法。
有没有办法做到这一点,而不重复遍历列表,以找到相似的植物,然后排序每一天,然后追加?我很抱歉这个问题的措辞很糟糕。
发布于 2014-06-25 08:27:39
虽然Vakh’s answer是正确的,但它是不必要的复杂。
通常,实现您自己的密钥类的工作不会有回报。您可以使用List
作为键,这意味着由于装箱原语值而造成的轻微开销,但考虑到我们在这里执行类似哈希的操作,它将是可以忽略不计的。
排序不必使用for
循环,更糟糕的是,使用Comparator
的匿名内部类。为什么我们有溪流和羔羊?您可以使用像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())));
就这样。
发布于 2014-06-24 20:50:55
使用Collectors.groupBy
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();
}
});
}
发布于 2014-06-24 20:45:01
我会根据它们的共同特点对它们进行分组,并比较类似的结果。
for(List<Plant> plantGroup : allPlants.stream().collect(Collectors.groupingBy(
p -> p.camera+'/'+p.measurement+'/'+p.replicate)).values()) {
// compare the plants in the same group
}
https://stackoverflow.com/questions/24395752
复制相似问题