“This is the 19th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”.

1. Introduction

Searching for different elements in a list is one of the most common tasks faced by programmers. Starting with Java 8 with Streams, we have a new API to work with data using functional methods.

In this article, we show four ways to filter collections using specific properties of objects in the list.

2. Use the Stream API

The Stream API provides a distinct() method that returns distinct elements of a list based on the Equals () method of the Object class.

However, it becomes less flexible if we want to filter by specific attributes. One of our alternatives is to write a filter to maintain state.

2.1. Use status filters

One solution is to implement stateful Predicate:

public static <T> Predicate<T> distinctByKey( 
    Function<? superT, ? > keyExtractor) { 
    
    Map<Object, Boolean> seen = new ConcurrentHashMap<>(); 
    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; 
}
Copy the code

To test it, we’ll use the following Person class with attributes age, email, and name:

public class Person { 
    private int age; 
    private String name; 
    private String email; 
    // getters and setters 
}
Copy the code

Gets the new filter collection by name

List<Person> personListFiltered = personList.stream()
    .filter(distinctByKey(p -> p.getName()))
    .collect(Collectors.toList());
Copy the code

3. Use Eclipse Collections

Eclipse Collections is a Java class library that provides additional methods for working with flows and Collections in Java.

3.1. Use ListIterate. Distinct ()

The Listiterate.distinct () method allows us to filter the flow using various HashingStrategies. These policies can be defined using lambda expressions or method references.

If we want to filter by name:

List<Person> personListFiltered = ListIterate
    .distinct(personList, HashingStrategies.fromFunction(Person::getName));
Copy the code

Alternatively, if the attributes we want to use are primitive attributes (int, long, double), we can use a specialized function like this:

List<Person> personListFiltered = ListIterate.distinct( 
    personList, HashingStrategies.fromIntFunction(Person::getAge));
Copy the code

3.2. The Maven dependencies

<dependency> 
    <groupId>org.eclipse.collections</groupId> 
    <artifactId>eclipse-collections</artifactId> 
    <version>8.2.0</version> 
</dependency>
Copy the code

4. Use Vavr (Javaslang)

This is the Java 8 function library that provides immutable data and function control structures.

4.1. Use the List. DistinctBy

To filter lists, the class provides its own List class with a distinctBy() method that allows us to filter by attributes of the objects it contains:

List<Person> personListFiltered = List.ofAll(personList) 
    .distinctBy(Person::getName) 
    .toJavaList();
Copy the code

4.2. The Maven dependencies

<dependency> 
    <groupId>io.vavr</groupId> 
    <artifactId>vavr</artifactId> 
    <version>0.9.0</version> 
</dependency>
Copy the code

5. Use StreamEx

The library provides useful classes and methods for Java 8 stream processing.

5.1. Use StreamEx. Distinct

Among the classes provided is StreamEx, which has a distinct method to which we can send references to the attributes we want to distinguish:

List<Person> personListFiltered = StreamEx.of(personList) 
    .distinct(Person::getName) 
    .toList();
Copy the code

5.2. The Maven dependencies

<dependency> 
    <groupId>one.util</groupId> 
    <artifactId>streamex</artifactId> 
    <version>0.6.5</version> 
</dependency>
Copy the code

6. The final

Creation is not easy, if you feel that this article is helpful to you, please pay more attention to, a lot of praise!! Thank you!!!!!