英文:
Filter attribute from a list of object nested in another list of object using stream
问题
对于以下的类结构,从 List<SomeClass> 中,对于给定的 name 和 fieldName,我想要得到一组 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 = "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;
    }
    
}
答案2
得分: 1
使用flatMap对List<SomeField>进行扁平化,然后根据条件进行过滤,然后仅映射fieldValue并获取fieldValue的列表。
List<String> res = classes.stream()
    .filter(e -> e.getName().equalsIgnoreCase(givenName))
    .flatMap(m  -> m.getSomeField().stream())
    .filter(f -> f.getFieldName().equalsIgnoreCase(givenFieldName))
    .map(e -> e.getFieldValue())
    .collect(Collectors.toList());
英文:
Use flatMap to flat the List<SomeField> then filter by condition then map only fieldValue and get the list of fieldValue.
List<String> res = classes.stream()
            .filter(e -> e.getName().equalsIgnoreCase(givenName))
            .flatMap(m  -> m.getSomeField().stream())
            .filter(f -> f.getFieldName().equalsIgnoreCase(givenFieldName))
            .map(e -> e.getFieldValue())
            .collect(Collectors.toList());
专注分享java语言的经验与见解,让所有开发者获益!



评论