简体   繁体   中英

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

For the following class structure, from a List<SomeClass> , for a given name and fieldName , I want to get a list of fieldValue s. 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"]

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());

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;
    }
    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM