在Java中使用Lambda对对象列表进行分组

时间:2018-12-11 14:23:45

标签: java java-8

我有这张桌子

Set    question     answer
1        A             X
1        B             X
1        C             X 
1        D             X
2        A             Y
2        B             Y
2        C             Y
2        D             Y

我需要转换为以下对象

class Assessment{
    integer setId
    Map<String,String> questiontoanswer
}

Set<question,answer>的映射进行分组,因此上表的输出应为

List<Assessment> [1 <A:X,B:X,C:X,D:X>, 2 <A:Y,B:Y,C:Y,D:Y>]

我不能用lambda来获得它。

2 个答案:

答案 0 :(得分:1)

这是使用收集器的另一种解决方案

public  class Assessment{
    public Integer set;
    public Map<String,String> questiontoanswer = new HashMap<>();

    public void accept(Row r) {
        this.set = r.set;
        this.questiontoanswer.put(r.question, r.answer);
    }

    public Assessment combine(Assessment other) {
        return this;
    }

    @Override
    public String toString() {
        return "Assessment [set=" + set + ", questiontoanswer=" + questiontoanswer + "]";
    }

}

和实际代码

    List<Row> rows = Arrays.asList(

        new Row(1,"A","X"),
        new Row(1,"B","X"),
        new Row(1,"C","X"),
        new Row(1,"D","X"),

        new Row(2,"A","Y"),
        new Row(2,"B","Y"),
        new Row(2,"C","Y"),
        new Row(2,"D","Y")
            );

    Collector<Row, Assessment, Assessment> collector = Collector.of(Assessment::new, Assessment::accept, Assessment::combine);

    Map<Integer, Assessment> result = rows.stream().collect(Collectors.groupingBy(Row::getSet, collector));
    System.out.println(result.values());

答案 1 :(得分:0)

这应该有效 步骤是

  • 按setId将输入分组,这将创建一个以setIds作为键并将相关输入列表作为值的映射
  • 对于每个分组的输入列表,然后将其变成一个问答地图。结果将是地图地图。
  • 通过简单的地图操作将结果转换为评估列表

代码包含2个作为单元测试断言的示例。实践证明

@Test
public void test(){
    List<InputObject> inputs = new LinkedList<>();
    inputs.add(new InputObject(1,"A","X"));
    inputs.add(new InputObject(1,"B","X"));
    inputs.add(new InputObject(1,"C","X"));
    inputs.add(new InputObject(1,"D","X"));

    inputs.add(new InputObject(2,"A","Y"));
    inputs.add(new InputObject(2,"B","Y"));
    inputs.add(new InputObject(2,"C","Y"));
    inputs.add(new InputObject(2,"D","Y"));

    Map<Integer, Map<String, String>> resultingMap = inputs.stream().collect(Collectors.groupingBy(InputObject::getSet, Collectors.toMap(InputObject::getQuestion, InputObject::getAnswer)));
    List<Assessment> result = resultingMap.entrySet().stream().map(entry -> new Assessment(entry.getKey(), entry.getValue())).collect(Collectors.toList());

    Map<String,String> expectedSet1Data = new LinkedHashMap<>();
    expectedSet1Data.put("A","X");
    expectedSet1Data.put("B","X");
    expectedSet1Data.put("C","X");
    expectedSet1Data.put("D","X");

    Map<String,String> expectedSet2Data = new LinkedHashMap<>();
    expectedSet2Data.put("A","Y");
    expectedSet2Data.put("B","Y");
    expectedSet2Data.put("C","Y");
    expectedSet2Data.put("D","Y");

    assertEquals(new Assessment(1,expectedSet1Data),result.get(0));
    assertEquals(new Assessment(2,expectedSet2Data),result.get(1));
}

@AllArgsConstructor
@Getter
private class InputObject{
    private int set;
    private String question;
    private String answer;
}

@Getter
@AllArgsConstructor
@Data
class Assessment{
    Integer setId;
    Map<String,String> questiontoanswer;
}