在Java中使用流式传输来映射的嵌套列表

时间:2019-07-16 10:37:15

标签: java java-8 stream java-stream nested-lists

我在将数据转换为地图时遇到了一些问题,这是我的数据:

例如

[
  [abc, pqr, xyz], 
  [1, 2, 3], 
  [4, 5, 6],
  [1, 7, 8]
]

我必须将其转换为地图,如下所示:

{
  1: [
    {abc:1, pqr:2,xyz:3},
    {abc:1, pqr:7,xyz:8}
  ],
  4: [
    {abc:4, pqr:5,xyz:6}
  ]
}

就基本而言,我知道该怎么做,但对于流而言,我尝试使用flatMap时却没有得到,通过流来简化方法,但也许我做错了很多。所以,请问有人可以帮我吗?

我尝试了一些对flatMap的尝试,但都遵循以下步骤,但坚持要做的事情:

List<List<Object>> dd = new ArrayList<List<Object>>();
final List<Object> dd1 = new ArrayList<Object>();
dd1.add("abc");
dd1.add("pqr");
dd1.add("xyz");
dd.add(dd1);

List<Object> dd2 = new ArrayList<Object>();
dd2.add("1");
dd2.add("2");
dd2.add("3");
dd.add(dd2);

dd2 = new ArrayList<Object>();
dd2.add("4");
dd2.add("5");
dd2.add("6");
dd.add(dd2);

Map<String, Object> m =  dd.stream().collect(Collectors.toMap(s -> (String) s.get(0), s -> s));
System.out.println(m);

Map<String, Object> m1 =  dd.stream().reduce((l1,l2) -> {
    return (new Map<String, Object>()).put(dd1.get(l2), l2);
}).orElse(new Map<String, Object>());

我在上面的代码中发现语法错误。另外,提供一些良好的链接,在其中可以很好地学习流式传输。

2 个答案:

答案 0 :(得分:1)

// get header and remove it from dataframe
List<String> header = dd.remove(0);

// key -> first element of row
// value -> extract from getValue method
// merge function -> merge both lists in case of conflict
Map<String, List<Map<String, String>>> tableAsMap = dd.stream().collect(Collectors.toMap(row -> row.get(0), row -> getValue(row, header), (list1, list2) -> {
    list1.addAll(list2);
    return list1;
}));

public List<Map<String, String>> getValue(List<String> row, List<String> header) {
    Map<String, String> map = new HashMap<>();
    IntStream.range(0, header.size())
            .forEach(idx -> map.put(header.get(idx), row.get(idx)));
    List<Map<String, String>> ret = new ArrayList<>();
    ret.add(map);
    return ret;
}

答案 1 :(得分:0)

您可以将整个代码简化为:

List<String> header = dd.remove(0);
Map<Integer, List<Map<String, Integer>>> result = dd.stream()
        .map(row -> IntStream.range(0, Math.min(row.size(), header.size())).boxed()
                .collect(Collectors.toMap(header::get, i -> Integer.parseInt(row.get(i)))))
        .collect(Collectors.groupingBy(m -> m.get("abc")));

首先使用List.remove()提取标头。之后,您可以通过将列表索引替换为标题字段作为键来为每行创建一个映射(还将值解析为int)。最后,您可以将Collectors.groupingBy()m -> m.get("abc")结合使用,以按abc值对结果进行分组。