Today, I walk you through Java 8 Stream Distinct Examples using stream API. You can filter or collect all distinct elements from a collection by using distinct() of Stream API. In case, we have to process a collection of complex objects we need to write a custom function for the specific filtering purpose. Let’s dive into it.
Java 8 Stream Distinct Examples
1. Java 8 distinct example
Now, we are finding all distinct strings without case sensitive from the String collection.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class StreamDistinctDemo { public static void main(String[] args) { Collection<String> list = Arrays.asList("java", "nodejs", "Java", "php", "C#", "c#", "JAVA"); // toLowerCase and distinct only List<String> distinctElements = list.stream().map(String::toLowerCase).distinct().collect(Collectors.toList()); // print the result System.out.println(distinctElements); } } |
Output
1 |
[java, nodejs, php, c#] |
2. Java 8 stream distinct by key
The above distinct example is quite simple and easy for us. In fact, we need to deal with objects or complex types.
We’re considering a POJO as below
1 2 3 4 5 6 7 |
public class People { public int age; public String gender; public String name; //getter and setter } |
Until now, Java doesn’t support any native API for filtering distinct by object property directly, even date object. We have to create a utility function that matches our requirements. Our utility function will filter distinct by the name property of People object, like this.
1 2 3 4 5 6 7 |
/** * Stateful filter. T is type of stream element, K is type of extracted key. */ public static Predicate distinctByKey(Function<? super T, Object> key) { Map<Object, Boolean> map = new ConcurrentHashMap<>(); return t -> map.putIfAbsent(key.apply(t), Boolean.TRUE) == null; } |
Here is a function that returns a predicate that maintains state about what it’s seen previously, and that returns whether the given element was seen for the first time.
Writing the demo program that is the main part of our Java 8 Stream Distinct Examples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public class StreamDistinctDemo2 { public static void main(String[] args) { People a = new People(28, "M", "Mr A"); People b = new People(25, "M", "Mr B"); People c = new People(21, "M", "Mr B"); People d = new People(21, "M", "Mr B"); // A collection of duplicated elements Collection list = Arrays.asList(a, b, c,d); // Get distinct only List distinctElements = list.stream().filter(distinctByKey(p -> p.getName())) .collect(Collectors.toList()); // print the distinct result System.out.println(distinctElements); // Get distinct with multiple keys List distinctMultiKeys = list.stream().filter(distinctByKey(p -> p.getName() + p.getAge())) .collect(Collectors.toList()); // print the distinct result System.out.println(distinctMultiKeys); } public static Predicate distinctByKey(Function<? super T, Object> key) { Map<Object, Boolean> map = new ConcurrentHashMap<>(); return t -> map.putIfAbsent(key.apply(t), Boolean.TRUE) == null; } } |
Output
That’s all about the Java 8 Stream Distinct Examples. If you want to know further other Java 8 resources, please check out Java 8 tutorials.
References
Processing Data with Java SE 8 Streams
Download the complete source code, click link below
Java8StreamDistinctExamples.zip (301 downloads)