java:收集并组合列表中的数据

时间:2014-06-24 20:32:45

标签: java java-8 concatenation java-stream

在我的程序中,我有一个植物列表,每个植物都有一个测量(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(新工厂值)附加值的方法。

有没有办法这样做而不反复遍历列表来找到类似的植物,然后每天按时间排序然后追加?对于这个问题的可怕措辞,我感到很抱歉。

4 个答案:

答案 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)

使用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();
                       }
                     });
}

答案 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());