Java 8收集并更改结果的格式

时间:2017-05-17 06:21:34

标签: java-8 java-stream

我有一个名为Name | 1 | 2 ... | 11 | ... | 19 Man-- | .............. | 1000 Agu-- | ............................| 5000 的数据结构,其中包含名为MyPojotimename的字段(所有字符都在字符串中)。我尝试按如下方式进行分组:

timetaken

请注意,我使用了 List<MyPojo> myPojos = Arrays.asList( new MyPojo("2017", "ABC", "30"), new MyPojo("2017", "ABC", "20"), new MyPojo("2016", "ABC", "25"), new MyPojo("2017", "XYZ", "40") ); Map<String, Map<String, Double>> resultMap = myPojos.stream() .collect(Collectors.groupingBy(MyPojo::getName, Collectors.groupingBy(MyPojo::getTime, Collectors.averagingDouble(MyPojo::getTimeTakenAsDouble)))); 方法将getTimeTakenAsDouble字符串转换为double值。

结果如下:

timetaken

但是,我的前端开发人员希望数据采用以下格式:

    {ABC={2017=25.0, 2016=25.0}, XYZ={2017=40.0}}

    {ABC={2017=25.0, 2016=25.0}, XYZ={2017=40.0, 2016=0.0}}

我正在考虑对 [ { "time": "2017", "name": "ABC", "avgTimeTaken": 25.0 }, { "time": "2017", "name": "XYZ", "avgTimeTaken": 40.0 }, { "time": "2016", "name": "ABC", "avgTimeTaken": 25.0 }, { "time": "2016", "name": "XYZ", "avgTimeTaken": 0.0 } ] 执行迭代并准备第二种格式。我试图在resultMap上再次执行迭代。还有其他方法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:4)

实际上,你想要达到的目标非常有趣。就像你试图做某种逻辑padding一样。我这样做的方法是使用Collectors.collectingAndThen。一旦结果出现 - 我只需用必要的数据填充它。

请注意,我使用Sets.difference中的guava,但可以很容易地将其放入静态方法中。还有其他操作。

所以我认为你的MyPojo看起来像这样:

 static class MyPojo {

    private final String time;

    private final String name;

    private final String timetaken;

    public MyPojo(String time, String name, String timetaken) {
        super();
        this.name = name;
        this.time = time;
        this.timetaken = timetaken;
    }

    public String getName() {
        return name;
    }

    public String getTime() {
        return time;
    }

    public String getTimetaken() {
        return timetaken;
    }

    public static double getTimeTakenAsDouble(MyPojo pojo) {
        return Double.parseDouble(pojo.getTimetaken());
    }
}

我检查过的输入数据是:

 List<MyPojo> myPojos = Arrays.asList(
            new MyPojo("2017", "ABC", "30"),
            new MyPojo("2017", "ABC", "20"),
            new MyPojo("2016", "ABC", "25"),
            new MyPojo("2017", "XYZ", "40"),
            new MyPojo("2018", "RDF", "80"));

以下是执行所需操作的代码:

 Set<String> distinctYears = myPojos.stream().map(MyPojo::getTime).collect(Collectors.toSet());

 Map<String, Map<String, Double>> resultMap = myPojos.stream()
            .collect(Collectors.groupingBy(MyPojo::getName,
                    Collectors.collectingAndThen(
                            Collectors.groupingBy(MyPojo::getTime,
                                    Collectors.averagingDouble(MyPojo::getTimeTakenAsDouble)),
                            map -> {
                                Set<String> localYears = map.keySet();
                                SetView<String> diff = Sets.difference(distinctYears, localYears);
                                Map<String, Double> toReturn = new HashMap<>(localYears.size() + diff.size());
                                toReturn.putAll(map);
                                diff.stream().forEach(e -> toReturn.put(e, 0.0));
                                return toReturn;
                            }
                    )));

结果是:

{ABC={2016=25.0, 2018=0.0, 2017=25.0}, 
 RDF={2016=0.0, 2018=80.0, 2017=0.0}, 
 XYZ={2016=0.0, 2018=0.0, 2017=40.0}}