我有一个扁平化的数据结构(这实际上是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, .....);
我可以使用的工具是分组/映射/减少,但我无法找出正确的组合/嵌套来实现我想要的结果。
附言只是为了让这变得有趣。这是对数据库的外部连接查询,因此 Struct2 可能没有任何 Struct3 元素(因此 key3 是整数而不是 int(
示例数据:
键 1 值1 键 2 键 3 最终值 1 "值1" 2 3 "最终1" 1 "值1" 2 4 "最终2" 1 "值1" 3 空空 5 "值2" 6 7"最终3">
我期待如下结果
[{ "键 1" : 1, "值 1" : "值 1", "内部" : [ { "键 2" : 2, "内部" : [ { "键3" : 3, "最终值" : "final1" }, { "键3" : 4, "最终值" : "final2" }], }, { "键2" : 3, "内部" : [] }], }, { "键1" : 5, "值 1" : "值 2", "内部" : [ { "键2" : 6, "内部" : [ { "键3" : 7, "最终值" : "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
.....
}
提前致谢
斯图
在类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();