使用流(Stream)从另一个对象列表嵌套的对象列表中筛选属性。

huangapple go评论86阅读模式
英文:

Filter attribute from a list of object nested in another list of object using stream

问题

对于以下的类结构,从 List<SomeClass> 中,对于给定的 namefieldName,我想要得到一组 fieldValue 值的列表。可能会有多个 name 的出现。

class SomeClass {
    String name;
    List<SomeField> fields;
}

class SomeField {
    String fieldName;
    String fieldValue;
}

这是我迄今为止在没有使用流(stream)的情况下所做的 -

for (SomeClass aClass : classes) {
    if (aClass.getName().equalsIgnoreCase(givenName)) {
        for (SomeField aField : aClass.getSomeField()) {
            if (aField.getFieldName().equalsIgnoreCase(givenFieldName)) {
                outputList.add(aField.getFieldValue());
            }
        }
    }
}

我尝试将此转换为流(stream),但我只达到了这里。我无法弄清楚如何进行下一步(从这一点开始获取 SomeField 列表并根据 fieldName 进行过滤) -

classes.stream()
       .filter(e -> e.getName().equalsIgnoreCase(givenName))
       .collect(Collectors.toList());

希望能得到帮助。

示例输入:

[
    {
        "name": "a",
        "fields": [
            {
                "fieldName": "n1",
                "fieldValue": "v1"
            },
            {
                "fieldName": "n2",
                "fieldValue": "v2"
            }
        ]
    },
    {
        "name": "a",
        "fields": [
            {
                "fieldName": "n1",
                "fieldValue": "v3"
            }
        ]
    },
    {
        "name": "b",
        "fields": [
            {
                "fieldName": "n1",
                "fieldValue": "v4"
            }
        ]
    }
]

对于 givenName = "a"givenFieldName = "n1"

期望的输出:["v1", "v3"]

英文:

For the following class structure, from a List<SomeClass>, for a given name and fieldName, I want to get a list of fieldValues. There can be multiple occurrences of name

class SomeClass {
    String name;
    List<SomeField> fields;
}

class SomeField {
    String fieldName;
    String fieldValue;
}

This is what I have done so far without stream -

				for (SomeClass aClass : classes) {

					if (aClass.getName().equalsIgnoreCase(givenName)) {

						for (SomeField aField : aClass.getSomeField()) {

							if (aField.getFieldName().equalsIgnoreCase(givenFieldName)) {

								outputList.add(aField.getFieldValue());

							}
						}
					}
				}

I have tried to convert this to stream, but I only reached till here. I could not figure out how to proceed to the next step (getting list of SomeField from this point and filtering based on fieldName) -

classes.stream()
			.filter(e -> e.getName().equalsIgnoreCase(givenName))
			.collect(Collectors.toList());

Any help would be appreciated.

Sample input:

  [
   {
      "name":"a",
      "fields":[
         {
            "fieldName":"n1",
            "fieldValue":"v1"
         },
         {
            "fieldName":"n2",
            "fieldValue":"v2"
         }
      ]
   },
   {
      "name":"a",
      "fields":[
         {
            "fieldName":"n1",
            "fieldValue":"v3"
         }
      ]
   },
   {
      "name":"b",
      "fields":[
         {
            "fieldName":"n1",
            "fieldValue":"v4"
         }
      ]
   }
]

for givenName = "a" and givenFieldName = "n1" :

expected output : ["v1","v3"]

答案1

得分: 2

使用map()flatMap()

public class Main {
    
    public static void main(String[] args) {
        
        String givenName = "a";
        String givenFieldName = "n1";
        
        List<SomeClass> classes = new ArrayList<>();
        classes.add(new SomeClass("a", List.of(new SomeField("n1", "v1"), new SomeField("n2", "v2"))));
        classes.add(new SomeClass("a", List.of(new SomeField("n1", "v3"))));
        classes.add(new SomeClass("b", List.of(new SomeField("n1", "v4"))));
        
        
        List<String> result = classes
                .stream()
                .filter(c -> c.name.equalsIgnoreCase(givenName))
                .flatMap(c -> c.fields.stream())
                .filter(f -> f.fieldName.equalsIgnoreCase(givenFieldName))
                .map(f -> f.fieldValue)
                .collect(Collectors.toList());
        
        System.out.println(result);
        
    }
    
}

class SomeClass {
    
    String name;
    List<SomeField> fields;
    
    public SomeClass(String name, List<SomeField> fields) {
        this.name = name;
        this.fields = fields;
    }
    
}

class SomeField {
    
    String fieldName;
    String fieldValue;
    
    public SomeField(String fieldName, String fieldValue) {
        this.fieldName = fieldName;
        this.fieldValue = fieldValue;
    }
    
}
英文:

Use map() and flatMap().

public class Main {
    
    public static void main(String[] args) {
        
        String givenName = &quot;a&quot;;
        String givenFieldName = &quot;n1&quot;;
        
        List&lt;SomeClass&gt; classes = new ArrayList&lt;&gt;();
        classes.add(new SomeClass(&quot;a&quot;, List.of(new SomeField(&quot;n1&quot;, &quot;v1&quot;), new SomeField(&quot;n2&quot;, &quot;v2&quot;))));
        classes.add(new SomeClass(&quot;a&quot;, List.of(new SomeField(&quot;n1&quot;, &quot;v3&quot;))));
        classes.add(new SomeClass(&quot;b&quot;, List.of(new SomeField(&quot;n1&quot;, &quot;v4&quot;))));
        
        
        List&lt;String&gt; result = classes
                .stream()
                .filter(c -&gt; c.name.equalsIgnoreCase(givenName))
                .flatMap(c -&gt; c.fields.stream())
                .filter(f -&gt; f.fieldName.equalsIgnoreCase(givenFieldName))
                .map(f -&gt; f.fieldValue)
                .collect(Collectors.toList());
        
        System.out.println(result);
        
    }
    
}

class SomeClass {
    
    String name;
    List&lt;SomeField&gt; fields;
    
    public SomeClass(String name, List&lt;SomeField&gt; fields) {
        this.name = name;
        this.fields = fields;
    }
    
}

class SomeField {
    
    String fieldName;
    String fieldValue;
    
    public SomeField(String fieldName, String fieldValue) {
        this.fieldName = fieldName;
        this.fieldValue = fieldValue;
    }
    
}

答案2

得分: 1

使用flatMapList&lt;SomeField&gt;进行扁平化,然后根据条件进行过滤,然后仅映射fieldValue并获取fieldValue的列表。

List&lt;String&gt; res = classes.stream()
    .filter(e -&gt; e.getName().equalsIgnoreCase(givenName))
    .flatMap(m  -&gt; m.getSomeField().stream())
    .filter(f -&gt; f.getFieldName().equalsIgnoreCase(givenFieldName))
    .map(e -&gt; e.getFieldValue())
    .collect(Collectors.toList());
英文:

Use flatMap to flat the List&lt;SomeField&gt; then filter by condition then map only fieldValue and get the list of fieldValue.

List&lt;String&gt; res = classes.stream()
.filter(e -&gt; e.getName().equalsIgnoreCase(givenName))
.flatMap(m  -&gt; m.getSomeField().stream())
.filter(f -&gt; f.getFieldName().equalsIgnoreCase(givenFieldName))
.map(e -&gt; e.getFieldValue())
.collect(Collectors.toList());

huangapple
  • 本文由 发表于 2020年7月24日 02:29:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63060861.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定