Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting only required objects from a list using Java 8 Streams

Consider a Parent class with the attributes attrib1, attrib2 and List<Child> child with its corresponding getters and setters.

The Child is another class with five attributes attrib1-attrib5 with its corresponding getters and setters.

Now I created a List<Parent> parent. Then I want to filter out a List<Parent> with following condition:- Child.Attrib1 > 10;

So I created the following query by Java 8 streams.

parent.stream().filter(e -> e.getChild().stream().anyMatch(c -> c.getAttrib1() > 10));

But the problem is I will get all the child in each Parent object. Here I want to get only those child object in List<Child> that obeys the given condition.

How should I remove all the child objects in List that doesn't obeys the condition and get the new List.

like image 234
Manu Joy Avatar asked Aug 21 '15 04:08

Manu Joy


People also ask

How do I get a list of fields from a list of objects?

The list of all declared fields can be obtained using the java. lang. Class. getDeclaredFields() method as it returns an array of field objects.

How do you get an element from a list using stream?

To find an element matching specific criteria in a given list, we: invoke stream() on the list. call the filter() method with a proper Predicate. call the findAny() construct, which returns the first element that matches the filter predicate wrapped in an Optional if such an element exists.

How do you limit a stream in Java?

Syntax : Stream<T> limit(long N) Where N is the number of elements the stream should be limited to and this function returns new stream as output. Exception : If the value of N is negative, then IllegalArgumentException is thrown by the function.

What is the difference between findFirst and findAny Java 8?

The findAny() method returns any element from a Stream, while the findFirst() method returns the first element in a Stream.


2 Answers

What you need is a Stream<Child> if you want to receive all children. The following expression might do the trick:

parents.stream().flatMap(e -> e.getChildren().stream()).filter(c -> c.getAttrib1() > 10)

This should return all children of all parents in the list where the get attribute value is greater than 10.

If you want to update the parents list by removing all child elements that fail a condition, you can do the following:

parents.forEach(p -> p.getChildren().removeIf(c -> c.getAttrib1() > 10));

This doesn't create a new list. Instead it updates the parents list itself.

like image 123
Dakshinamurthy Karra Avatar answered Nov 12 '22 21:11

Dakshinamurthy Karra


As I can understand you should add additional filter for child lists:

 parent.stream().filter(e -> e.getChild().stream().anyMatch(c -> c.getAttrib1() > 10)).forEach(e -> e.setChild(e.getChild().stream().filter(c -> c.getAttrib1 > 10).collect(toList())))

If you have not setChild:

  • You can remove items from lists
  • Create completly new parent objects

To remove you can use iterator:

parent.stream().filter(e -> e.getChild().stream().anyMatch(c -> c.getAttrib1 > 10))
   .forEach(e -> {
      for(Iterator<Child> it = e.getChild().iterator(); it.hasNext();){
          Child cur = it.next();
          if(cur.getAttrib1() <= 10) it.remove();
    }
})
like image 31
sibnick Avatar answered Nov 12 '22 19:11

sibnick