Notes on practical usage of Java 8 stream filtering.

Stream Filtering

Stream<T> references a sequence of T values, and exposes a set of aggregate operations we can use to manipulate data in a pipeline.

As an example, we can find the name of any people older than 20.

System.out.printf("%n after select: %s - %s - %s", index, selection2, selection3); //$NON-NLS-1$
String name = persons.stream()
  .filter(p -> p.getName.startsWith("P"))
  .map(Person::getName)
  .findAny()
  .orElse("");

In java, you can loop on a variable using the foreach filter.

for(Shape s : shapes){
  s.setColor(RED);
}

Iterate

With streams, this is the equivalent you can do the same in

shapes.forEach(s -> s.setColor(RED));
  • .foreEach is an iteration internal to the stream

Filter

Set a specific value only to items matching a filter.

shapes.stream()
  .filter(s -> s.getColor()==BLUE)
  .forEach( s -> s.setColor(RED));
  • .filter filters only some elements of the stream

Collect

Collect all the objects matching our filter returning a Collection.

List<Shape> blueShapes= shapes.stream()
  .filter(s -> s.getColor()==BLUE)
  .collect(Collectors.toList());
  • .collect collects the objects of the stream into a non-streaming data structure.

Map

Example 3: Collect all derived properties of objects matching our filter.

List<Box> blueBoxes = shapes.stream()
  .filter(s -> s.getColor()==BLUE)
  .map(s -> s.getContainingBox())
  .collect(Collectors.toList());
  • .map : get a stream of objects of a type and map each of them into another type. As a result, after map, you are working on a stream of different type.

Advanced Filtering

Filter and return the first element or else null

List<Person> persons = ..
Person p = persons.stream()
  .filter(p -> p.getName().contains("Mark"))
  .findFirst()
  .orElse(null);
  • .findFirst returns an optional value
  • .orElse manages the case when there is no value

Filter by type and collect into a new Specific list

List<Person> persons = ..
List<Employee> emps = persons.stream()
  .filter(Employee.class::isInstance)
  .map(Employee.class::cast)
  .collect(Collectors.toList());

Flatten a list of lists

For each person, get the list of addresses. Then get all the addresses of all the persons and put them into a set.

List<Person> persons = ..
Set<Address> addresses = persons.stream()
  .map(Person::getAddressList)
  .flatMap(Collection::stream)
  .collect(Collectors.toSet());
  • .flatMap flattens a stream of lists into a simple stream of the objects that are contained.

And when we want to preserve the original order of the list, we collect our data into a LinkedHashSet.

// same as above ..
  .collect(Collectors.toSet(LinkedHashSet::new));

References


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *