将List <map>转换为其他List <map>,其中包含来自第一个List的一些键,以及整个第一个列表

时间:2018-02-22 20:40:16

标签: java list dictionary java-8

我有一个List<Map<String, Object>>包含以下数据,显示为json以便于阅读:

data1 = [ {
    "siteId" : 1,
    "siteName" : "Site 1",
    "member" : "John Doe",
    "age" : 20
}, {
    "siteId" : 1,
    "siteName" : "Site 1",
    "member" : "James Doe",
    "age" : 30
}, {
    "siteId" : 2,
    "siteName" : "Site 2",
    "member" : "Jane Doe",
    "age" : 40
}, {
    "siteId" : 2,
    "siteName" : "Site 2",
    "member" : "Judy Doe",
    "age" : 50
} /* etc ... */ ]

我需要将其转换为:

data2 = [ {
    "siteId" : 1,
    "siteName" : "Site 1",
    "values" : [ {
        "siteId" : 1,
        "siteName" : "Site 1",
        "member" : "John Doe",
        "age" : 20
    }, {
        "siteId" : 1,
        "siteName" : "Site 1",
        "member" : "James Doe",
        "age" : 30
    } ]
}, {
    "siteId" : 2,
    "siteName" : "Site 2",
    "values" : [ {
        "siteId" : 2,
        "siteName" : "Site 2",
        "member" : "Jane Doe",
        "age" : 40
    }, {
        "siteId" : 2,
        "siteName" : "Site 2",
        "member" : "Judy Doe",
        "age" : 50
    } ]
} ]

如何以一种有效的(Java8-ish)方式避免多个嵌套循环呢?

修改

这是我迄今为止提出的最好的方法:

List<Map<String, Object>> data1 = service.getData1();
List<Map<String, Object>> data2 = new ArrayList<>();

Map<String, Object> t2 = new HashMap<String, Object>();

data1.forEach(item -> {
    String id = (String) item.get("siteId");
    if (!t2.containsKey(id)) {
        t2.put(id, item.get("siteName"));
    }
});

t2.forEach((k, v) -> {
    Map<String, Object> t3 = new HashMap<String, Object>();
    t3.put("siteId", k);
    t3.put("siteName", v);
    t3.put("values", r.stream().filter(line -> ((String) line.get("siteId")).equals(k)).collect(Collectors.toList()));
    data2.add(t3);
});

修改2

在咨询Maurice Perry的答案后,结果证明这是最佳解决方案:

public List<Map<String, Object>> transformListToGrouped2(final List<Map<String, Object>> r, final String key1, final String key2) {
    List<Map<String, Object>> values = new ArrayList<>();
    final List<Map<String, Object>> data2 = new ArrayList<>();
    Map<String, Object> prev = null;
    for (final Map<String, Object> cur : r) {
        if (prev == null || !prev.get(key1).equals(cur.get(key1))) {
            final Map<String, Object> obj = new HashMap<>();
            values = new ArrayList<>();
            obj.put(key1, cur.get(key1));
            obj.put(key2, cur.get(key2));
            obj.put("values", values);
            data2.add(obj);
        }
        values.add(cur);
        prev = cur;
    }
    return data2;
}

2 个答案:

答案 0 :(得分:1)

这应该这样做:

List<Map<String, Object>> values = null;
Map<String, Object> prev = null;
for (Map<String, Object> cur: data1) {
    if (prev == null || !prev.get("siteId").equals(cur.get("siteId"))) {
        Map<String,Object> obj = new HashMap<>();
        values = new ArrayList<>();
        obj.put("siteId", cur.get("siteId"));
        obj.put("siteName", cur.get("siteName"));
        obj.put("values", values);
        data2.add(obj);
    }
    values.add(cur);
    prev = cur;
}

答案 1 :(得分:0)

以下是更多Java-8尝试方法 -

class SiteInfo {
  int siteId
  String siteName
}

class VisitInfo {
  int siteId
  String siteName
  String member
  int age

  getSiteInfo {
   return new SiteInfo(siteId, siteName)
  }
}

class GroupedVisitInfo {
  int siteId
  String siteName
  List[VisitInfo] userVisits
}


// code

Map <SiteInfo, List<VisitInfo>> groupedVisitInfo = userVisitdata.stream().collect(groupingBy(VisitInfo::getSiteInfo));

尝试一下,让我知道你的意见。