首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java 8嵌套群

Java 8嵌套群
EN

Stack Overflow用户
提问于 2017-05-05 04:57:51
回答 2查看 2.9K关注 0票数 4

我有两个似乎解决不了的问题。第一个问题是,我需要一种方法,通过用户可以传入的1n个嵌套组来进行动态嵌套分组。

第二个问题是,我需要将结果平缓到键连接的地方,而不是嵌套的地方。

我的示例输入如下所示:

代码语言:javascript
运行
复制
    List<Map<String, String>> fakeData = new LinkedList<>();
    Map<String, String> data1 = new HashMap<>();
    data1.put("ip","10.0.1.0");
    data1.put("uid","root");
    data1.put("group","admin");
    fakeData.add(data1);

    Map<String, String> data2 = new HashMap<>();
    data2.put("ip","10.0.1.1");
    data2.put("uid","tiger");
    data2.put("group","user");
    fakeData.add(data2);

    Map<String, String> data3 = new HashMap<>();
    data3.put("ip","10.0.1.1");
    data3.put("uid","woods");
    data3.put("group","user");
    fakeData.add(data3);

最终结果包含一个映射键:

代码语言:javascript
运行
复制
{
  "10.0.1.1user": [
    {
      "uid": "tiger",
      "ip": "10.0.1.1",
      "group": "user"
    },
    {
      "uid": "woods",
      "ip": "10.0.1.1",
      "group": "user"
    }
  ],
  "10.0.1.0admin": [
    "uid": "root",
    "ip": "10.0.1.0",
    "group": "admin"
  ]
}

注意,这些键是连接的,而不是映射中的嵌套映射。

我正在尝试创建一个群,在那里它可以是动态的,而不需要任何运气:

代码语言:javascript
运行
复制
 fakeData.stream()
                .collect(groupingBy(map -> map.get("ip"),
                        groupingBy(map -> map.get("uuid"),
                                ... nested "n" times)));

这是我试图实现的接口:

代码语言:javascript
运行
复制
public Map<String, List<Map<String, String>>> doGrouping(List<String> columns, 
                                                   List<Map<String, String>> data);
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-05 06:12:34

尝试以下几点:

代码语言:javascript
运行
复制
public Map<String, List<Map<String, String>>> doGrouping(
        List<String> columns,
        List<Map<String, String>> data) {

    return data.stream()
        .collect(Collectors.groupingBy(
            elem -> columns.stream()
                .map(elem::get)
                .collect(Collectors.joining())));
}

首先,我对data进行了流,这是一个地图列表。我立即使用Collectors.groupingBy将流收集到一个列表映射中,并使用为流的每个元素计算的键。

计算钥匙是最棘手的部分。为此,我流进了给定的columns列表,并将其中的每一列转换为流元素的对应值。我通过Stream.map方法完成了这个任务,并将elem::map作为映射函数传递。最后,我使用Collectors.joining将这个内部流收集到一个字符串中,该字符串以一种高效的方式将流的每个元素连接成一个最终的字符串。

编辑:如果columns的所有元素都作为data中映射元素的键存在,那么上面的代码工作得很好。为了更安全起见,请使用以下内容:

代码语言:javascript
运行
复制
return data.stream()
    .collect(Collectors.groupingBy(
        elem -> columns.stream()
            .map(elem::get)
            .filter(Objects::nonNull)
            .collect(Collectors.joining())));

此版本从流中筛选出null元素,如果某些map元素不包含在columns列表中指定的键,则可能会发生这种情况。

票数 6
EN

Stack Overflow用户

发布于 2017-05-05 05:46:21

不确定是否使用流,但如果您更喜欢简单的java方式,则要容易得多。如果我正确理解你的问题,这里是你想要构建的方法。你可能需要稍微调整一下,以使它更快。

代码语言:javascript
运行
复制
public Map<String, List<Map<String, String>>> doGrouping(List<String> columns, List<Map<String, String>> data) {
    Map<String, List<Map<String, String>>> output = new HashMap<>();
    for (Map<String, String> map : data) {
        String key = "";
        for(String column :  columns) key += "".equals(key) ? (map.get(column)) : (":" + map.get(column));
        output.computeIfAbsent(key, k -> Arrays.asList(map));
    }
    return output;
}

测试:

代码语言:javascript
运行
复制
doGrouping(Arrays.asList("ip", "group"), fakeData)
>> {10.0.1.1:user=[{uid=tiger, ip=10.0.1.1, group=user}, {uid=woods, ip=10.0.1.1, group=user}], 10.0.1.0:admin=[{uid=root, ip=10.0.1.0, group=admin}]}

doGrouping(Arrays.asList("group"), fakeData)
>> {admin=[{uid=root, ip=10.0.1.0, group=admin}], user=[{uid=tiger, ip=10.0.1.1, group=user}, {uid=woods, ip=10.0.1.1, group=user}]}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43796825

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档