我有一个扁平化的数据结构(实际上是DB SQL查询的结果,所以会有很多重复的数据),我想将其转换为层次结构。
输入结构:
class Data {
int key1;
String value1;
int key2;
Integer key3;
String finalValue;
}
输出结构
class Struct1 {
int key1;
String value1;
List<Struct2> inner;
}
class Struct2 {
int key2;
List<Struct3> inner;
}
class Struct3 {
int key3;
String finalValue;
}
所以.....
List<Data> input = ....
List<Struct1> results = input.stream().collect(groupingBy(x->x.key1, .....);
我可以使用的工具是group / map / reduce,但是我无法计算出正确的组合/嵌套来获得想要的结果。
p.s。只是为了使这个有趣。这是对数据库的外部联接查询,因此Struct2可能没有任何Struct3元素(因此key3是Integer而不是int)
示例数据:
key1 value1 key2 key3 finalValue 1 "value1" 2 3 "final1" 1 "value1" 2 4 "final2" 1 "value1" 3 null null 5 "value2" 6 7 "final3"
我希望得到类似以下内容的结果
[{ "key1" : 1, "value1" : "value1", "inner" : [ { "key2" : 2, "inner" : [ { "key3" : 3, "finalValue" : "final1" }, { "key3" : 4, "finalValue" : "final2" }], }, { "key2" : 3, "inner" : [] }], }, { "key1" : 5, "value1" : "value2", "inner" : [ { "key2" : 6, "inner" : [ { "key3" : 7, "finalValue" : "final3" }] }]
这是一个答案,但我不是超级粉丝:
Map<Long, Data> groupByKey1 = data.stream().collect(groupingBy(x->x.key1));
List<Struct1> result = groupByKey1.entrySet().stream().map(this::createStruct1).collect(toList());
Struct1 createStruct1(Entry<Long, List<Data>> item) {
List<Struct2> struct2 = item.getValue().stream().collect(groupingBy(x->x.key2)).entrySet().stream().map(this::createStruct2).collect(toList());
// create and return Struct1
.....
}
第二次尝试(我认为这是我正在寻找的答案)
Map<Long, Data> groupByKey1 = data.stream().collect(groupingBy(x->x.key1, collectingAndThen(toList(), this::createStruct1));
Struct1 createStruct1(List<Data> item) {
List<Struct2> struct2 = item.stream().collect(groupingBy(x->x.key2, collectingAndThen(toList(), this::createStruct2));
// create and return Struct1
.....
}
预先感谢
斯图
答案 0 :(得分:0)
在类Struct1
中创建一个构造函数,该构造函数接受一行的所有值,为其他类编写类似的构造函数,然后从Struct1
构造函数调用它们。完成后,编写正确的流应该很容易。
public Struct1(int key1, String value1, int key2, Integer key3, String finalValue) {
this.key1 = key1;
this.value1 = value1;
Struct3 str3 = new Struct3(key3, finalValue);
Struct2 str2 = new Struct2(key2, str3);
this.inner = new ArrayList<>();
this.inner.add(str2);
}
这里是处理创建和更新Struct1对象的示例。老派循环。
Map<Integer, Struct1> cache = new HashMap<>();
for (Data data: input) {
Struct1 str1 = cache.get(data.key1);
if (str1 == null) {
str1 = new Struct1(data.key1, data.value1, data.key2, data.key3, data.finalValue);
cache.put(str1.key1, str1);
} else {
str1.update(data.key2, data.key3, data.finalValue);
}
}
List<Struct1> result = cache.values();