简体   繁体   English

获取 Map <string, list<object> &gt; 从列表<object>其中键是对象的字段之一<div id="text_translate"><p>我有一个 object 如下</p><pre>public class Model { private String key; private String data1; private String data2; private String data3; // getters }</pre><p> 这些模型的列表正在通过数据层返回。 现在我想创建一个Map&lt;String, List&lt;Model&gt;&gt; ,其键是Model class 中的“键”字段。 有多个具有不同数据值的重复“键”。 我有以下现有解决方案,但需要一种更简单更好的方法。 没有广泛使用 Java 8 所以对大多数方法不太熟悉,并且由于我没有时间研究而需要尽快解决。</p><pre> List&lt;Model&gt; models = modelRepo.getAllModels(); Set&lt;String&gt; keys = models.stream().map(Model::getKey).collect(Collectors.toSet()); Map&lt;String, List&lt;Model&gt;&gt; result = new HashMap&lt;&gt;(); keys.stream().forEach(key -&gt; { List&lt;Model&gt; modelList = new ArrayList&lt;&gt;(); models.stream().forEach(model -&gt; { if (model.getKey().equals(key)) { modelList.add(model); } }); result.put(key, modelList); });</pre></div></object></string,>

[英]Get Map<String, List<Object>> from List<Object> where the key is one of the fields of the objects

I've got an object as below我有一个 object 如下

public class Model {
    private String key;
    private String data1;
    private String data2;
    private String data3;

    // getters
}

A list of these Models is being returned via the data layer.这些模型的列表正在通过数据层返回。 Now I want to create a Map<String, List<Model>> with the key being the "key" field in the Model class.现在我想创建一个Map<String, List<Model>> ,其键是Model class 中的“键”字段。 There are multiple duplicate "key"s with different data values.有多个具有不同数据值的重复“键”。 I have the below existing solution but need a simpler and better way.我有以下现有解决方案,但需要一种更简单更好的方法。 Haven't used Java 8 extensively so not quite familiar with most of the methods and need a solution soon as I don't have time to research.没有广泛使用 Java 8 所以对大多数方法不太熟悉,并且由于我没有时间研究而需要尽快解决。

List<Model> models = modelRepo.getAllModels();
Set<String> keys = models.stream().map(Model::getKey).collect(Collectors.toSet());

Map<String, List<Model>> result = new HashMap<>();
keys.stream().forEach(key -> {
    List<Model> modelList = new ArrayList<>();
    models.stream().forEach(model -> {
        if (model.getKey().equals(key)) {
            modelList.add(model);
        }
    });
    result.put(key, modelList);
});

Use groupingBy for grouping Models by key which return Map使用groupingBy按返回 Map 的key对模型进行分组

Map<String, List<Model>> results = models.stream()
            .collect(Collectors.groupingBy(Model::getKey));

groupingBy method which only takes a function as its parameter. groupingBy方法,仅以 function 作为其参数。 The value that is returned by the function is used as a key to the map that we get from the groupingBy collector. function 返回的值用作我们从 groupingBy 收集器获得的 map 的键。

First of all, stream().forEach() can be replaced with forEach() as long as no intermediate operations are used.首先,只要不使用中间操作, stream().forEach()可以替换为forEach()

What you want is a typical use-case for Collectors.groupingBy with no further downstream collector:您想要的是Collectors.groupingBy的典型用例,没有进一步的下游收集器:

Map<String, List<Model>> result = models.stream()     // Stream<Model>
    .collect(Collectors.groupingBy(Model::getKey));   // Map<String, List<Model>>

You can use groupingBy:您可以使用 groupingBy:

public class Test1 {

    public static void main(String[] args) {
        List<Model> models = new ArrayList<>();
        models.add(new Model("a", "a1", "a2", "a3"));
        models.add(new Model("a", "a4", "a5", "a6"));
        models.add(new Model("c", "c1", "c2", "c3"));
        models.add(new Model("d", "d1", "d2", "d3"));
        models.add(new Model("d", "d4", "d5", "d6"));

        Map<String, List<Model>> result = models.stream().collect(Collectors.groupingBy(Model::getKey));

        result.forEach((a, b) -> System.out.println(a + " - " + b));
    }

    public static class Model {
        private String key;
        private String data1;
        private String data2;
        private String data3;

        public Model(String key, String data1, String data2, String data3) {
            this.key = key;
            this.data1 = data1;
            this.data2 = data2;
            this.data3 = data3;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getData1() {
            return data1;
        }

        public void setData1(String data1) {
            this.data1 = data1;
        }

        public String getData2() {
            return data2;
        }

        public void setData2(String data2) {
            this.data2 = data2;
        }

        public String getData3() {
            return data3;
        }

        public void setData3(String data3) {
            this.data3 = data3;
        }

        @Override
        public String toString() {
            return "Model{" +
                    "key='" + key + '\'' +
                    ", data1='" + data1 + '\'' +
                    ", data2='" + data2 + '\'' +
                    ", data3='" + data3 + '\'' +
                    '}';
        }
    }
}

Well for starters, the elegant way is that you can use the groupBy in stream() .对于初学者来说,优雅的方式是您可以在stream()中使用groupBy

Map<String, List<Model>> results = models.stream()
                                         .collect( Collectors.groupingBy(Model::getKey));

And if you are reluctant to use stream() , And also since you mention that you haven't used Java 8 extensively so not quite familiar with most of the methods.如果您不愿意使用stream() ,而且由于您提到您没有广泛使用 Java 8 ,因此对大多数方法不太熟悉。 There's always the traditional way of doing this with loops.使用循环总是有传统的方法。

    Map<String,List<Model>> results = new HashMap<>(  );

    for( Model m : models )
    {
        if( results.containsKey( m.getKey() ) )
        {
            results.get( m.getKey() ).add( m );
        }
        else
        {
            results.put( m.getKey(), new ArrayList<>( Collections.singleton(m) ) );
        }
    }

如何创建列表<object>带有字段字符串和 Map <string, set<string> &gt; 从另一个列表<object2><div id="text_translate"><p> Class Object2具有标准的 getter 并具有String字段folder 、 file和version 。 它被命名为SourceInfo</p><p> List&lt;SourceInfo&gt; source包含上面提到的三个字段。</p><p> 我的目标是从List&lt;SourceInfo&gt;创建一个List&lt;Info&gt; &gt; 。</p><p> 新List的 class 为Info ,如下图所示。</p><pre> public class Info { private final String folder; private final Map&lt;String, Set&lt;String&gt;&gt; file; public static Builder builder() { return new Builder(); } public static Builder builder(Info info) { return new Builder(info); } private Info(Builder builder) { this.folder = builder.folder; this.file = builder.file; } public String getFolder() { return folder; } public Map&lt;String, Set&lt;String&gt;&gt; getFile() { return file; } // autogenerated toString, hashCode, and equals public static class Builder { private String folder; private Map&lt;String, Set&lt;String&gt;&gt; file; private Builder() {} private Builder(Info info) { this.folder = info.folder; this.file = info.file; } public Builder with(Consumer&lt;Builder&gt; consumer) { consumer.accept(this); return this; } public Builder withFolder(String folder) { this.folder = folder; return this; } public Builder withFile(Map&lt;String, Set&lt;String&gt;&gt; file) { this.file = file; return this; } public Info build() { return new Info(this); } }</pre><p> 到目前为止,我尝试的是在构建器模式中创建一个集合。</p><pre> List&lt;SourceInfo&gt; source; // error: gc overhead limit exceeded List&lt;Info&gt; infoList = source.stream().map(e -&gt; Info.builder().withFolder(e.getFolder()).withFile(source.stream().collect(Collectors.groupingBy(SourceInfo::getKey, Collectors.mapping(SourceInfo::getVersion, Collectors.toSet())))).build()).collect(Collectors.toList()); Map&lt;String, Set&lt;String&gt;&gt; map = source.stream().collect(Collectors.groupingBy(SourceInfo::getKey, Collectors.mapping(SourceInfo::getVersion, Collectors.toSet()))); List&lt;Info&gt; info = source.stream().map(e -&gt; Info.builder().withFolder(e.getFolder()).withFile(map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))).build()).collect(Collectors.toList());</pre><p> 所需的 output。 以下语法可能已关闭。</p><pre> // [String, Map&lt;String, Set&lt;String&gt;&gt;] Info [folder, [key=file [value=version]]]...</pre><p> 我是 Java 的新手,不胜感激。</p><p> 我想了解如何使用 java8 和 for 循环来做到这一点。</p><p> 谢谢你。</p></div></object2></string,></object> - How to create a List<Object> with fields String and Map<String, Set<String>> from another List<Object2>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java 8 Stream convert list to map, where map key is an object derived from two fields of the list? - Java 8 Stream convert list to map, where map key is an object derived from two fields of the list? 如何从 Map 获取值,其中 Object 是密钥对列表? - How to get values from Map where Object is a list of key pairs? 如何创建列表<object>带有字段字符串和 Map <string, set<string> &gt; 从另一个列表<object2><div id="text_translate"><p> Class Object2具有标准的 getter 并具有String字段folder 、 file和version 。 它被命名为SourceInfo</p><p> List&lt;SourceInfo&gt; source包含上面提到的三个字段。</p><p> 我的目标是从List&lt;SourceInfo&gt;创建一个List&lt;Info&gt; &gt; 。</p><p> 新List的 class 为Info ,如下图所示。</p><pre> public class Info { private final String folder; private final Map&lt;String, Set&lt;String&gt;&gt; file; public static Builder builder() { return new Builder(); } public static Builder builder(Info info) { return new Builder(info); } private Info(Builder builder) { this.folder = builder.folder; this.file = builder.file; } public String getFolder() { return folder; } public Map&lt;String, Set&lt;String&gt;&gt; getFile() { return file; } // autogenerated toString, hashCode, and equals public static class Builder { private String folder; private Map&lt;String, Set&lt;String&gt;&gt; file; private Builder() {} private Builder(Info info) { this.folder = info.folder; this.file = info.file; } public Builder with(Consumer&lt;Builder&gt; consumer) { consumer.accept(this); return this; } public Builder withFolder(String folder) { this.folder = folder; return this; } public Builder withFile(Map&lt;String, Set&lt;String&gt;&gt; file) { this.file = file; return this; } public Info build() { return new Info(this); } }</pre><p> 到目前为止,我尝试的是在构建器模式中创建一个集合。</p><pre> List&lt;SourceInfo&gt; source; // error: gc overhead limit exceeded List&lt;Info&gt; infoList = source.stream().map(e -&gt; Info.builder().withFolder(e.getFolder()).withFile(source.stream().collect(Collectors.groupingBy(SourceInfo::getKey, Collectors.mapping(SourceInfo::getVersion, Collectors.toSet())))).build()).collect(Collectors.toList()); Map&lt;String, Set&lt;String&gt;&gt; map = source.stream().collect(Collectors.groupingBy(SourceInfo::getKey, Collectors.mapping(SourceInfo::getVersion, Collectors.toSet()))); List&lt;Info&gt; info = source.stream().map(e -&gt; Info.builder().withFolder(e.getFolder()).withFile(map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))).build()).collect(Collectors.toList());</pre><p> 所需的 output。 以下语法可能已关闭。</p><pre> // [String, Map&lt;String, Set&lt;String&gt;&gt;] Info [folder, [key=file [value=version]]]...</pre><p> 我是 Java 的新手,不胜感激。</p><p> 我想了解如何使用 java8 和 for 循环来做到这一点。</p><p> 谢谢你。</p></div></object2></string,></object> - How to create a List<Object> with fields String and Map<String, Set<String>> from another List<Object2> 从列表创建映射,其中键是内部和外部对象的一部分 - Creating map from list, where key is in part of inner and outer object 在 java 列表中转换<pojo>至 Map <string, list<object> &gt; 其中键是字段名称,值是按字段列出的值列表</string,></pojo> - Convert in java List<POJO> to Map<String, List<Object>> where the key is a field name and value is a list of values by field 从列表中删除对象 <Map<String,Object> &gt;在Java中 - removing objects from List<Map<String,Object>> in Java 根据对象列表中的某些字段获取最小对象 - Get Minimum object based on some fields from a List of objects 我们如何从地图上显示一个键及其值 <String, List<Object> &gt;一次在JSP页面上? - How Can we show One Key and its Values from Map<String, List<Object>> at a time on a JSP page? 对象列表 - 获取对象字段的不同计数 - List of objects - get object fields distinct count 如何从列表中删除键/值对<Map<String, Object> &gt; - How to remove the key/value pair from a List<Map<String, Object>>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM