Java Distinct Example
September 04, 2017
On this page we will provide Java 8 Stream distinct()
example. distinct()
returns a stream consisting of distinct elements of that stream. distinct()
is the method of Stream
interface. distinct()
uses hashCode()
and equals()
methods to get distinct elements. Hence our class must implement hashCode()
and equals()
methods. If distinct()
is working on ordered streams, then for duplicated elements, the elements appearing first in encounter order is preserved and in this way selection of distinct element is stable. In case of unordered streams, the selection of distinct elements is not necessarily stable and can change. distinct()
performs stateful intermediate operation.
In case of parallel pipelines for ordered stream, preserving stability for
distinct()
is expensive because it needs substantial buffering overheads. If consistency with encounter order is not necessary, then we should use unordered streams that can be achieved by using BaseStream.unordered()
method.
Now we will provide examples of Stream
distinct()
method.
Contents
1. Stream.distinct()
Find the declaration ofdistinct()
method.
Stream<T> distinct()
Stream
interface. Now find the example. In this example we have a list of string data type that contains duplicate elements.
DistinctSimpleDemo.java
package com.concretepage; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class DistinctSimpleDemo { public static void main(String[] args) { List<String> list = Arrays.asList("AA", "BB", "CC", "BB", "CC", "AA", "AA"); long l = list.stream().distinct().count(); System.out.println("No. of distinct elements:"+l); String output = list.stream().distinct().collect(Collectors.joining(",")); System.out.println(output); } }
No. of distinct elements:3 AA,BB,CC
2. Stream.distinct() with List of Objects
In this example we have a list of user object. The class will overridehashCode()
and equals()
in order to get distinct elements.
Book.java
package com.concretepage; public class Book { private String name; private int price; public Book(String name, int price) { this.name = name; this.price = price; } public String getName() { return name; } public int getPrice() { return price; } @Override public boolean equals(final Object obj) { if (obj == null) { return false; } final Book book = (Book) obj; if (this == book) { return true; } else { return (this.name.equals(book.name) && this.price == book.price); } } @Override public int hashCode() { int hashno = 7; hashno = 13 * hashno + (name == null ? 0 : name.hashCode()); return hashno; } }
package com.concretepage; import java.util.ArrayList; import java.util.List; public class DistinctWithUserObjects { public static void main(String[] args) { List<Book> list = new ArrayList<>(); { list.add(new Book("Core Java", 200)); list.add(new Book("Core Java", 200)); list.add(new Book("Learning Freemarker", 150)); list.add(new Book("Spring MVC", 300)); list.add(new Book("Spring MVC", 300)); } long l = list.stream().distinct().count(); System.out.println("No. of distinct books:"+l); list.stream().distinct().forEach(b -> System.out.println(b.getName()+ "," + b.getPrice())); } }
No. of distinct books:3 Core Java,200 Learning Freemarker,150 Spring MVC,300
3. Distinct by Property
distinct()
does not provide distinct elements by property or key. It works on the basis of hashCode()
and equals()
. If we want distinct element by a property or key, we can achieve it by a work around code. Find the code snippet.
static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) { Map<Object,Boolean> seen = new ConcurrentHashMap<>(); return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; }
filter()
method as follows.
list.stream().filter(distinctByKey(b -> b.getName()));
distinctByKey()
method. This method returns Predicate
instance that maintains state about what is seen previously using ConcurrentHashMap
. Find a complete example using
distinctByKey()
method to get distinct elements of our stream by class property.
DistinctByProperty.java
package com.concretepage; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Predicate; public class DistinctByProperty { public static void main(String[] args) { List<Book> list = new ArrayList<>(); { list.add(new Book("Core Java", 200)); list.add(new Book("Core Java", 300)); list.add(new Book("Learning Freemarker", 150)); list.add(new Book("Spring MVC", 200)); list.add(new Book("Hibernate", 300)); } list.stream().filter(distinctByKey(b -> b.getName())) .forEach(b -> System.out.println(b.getName()+ "," + b.getPrice())); } private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) { Map<Object,Boolean> seen = new ConcurrentHashMap<>(); return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; } }
Core Java,200 Learning Freemarker,150 Spring MVC,200 Hibernate,300
References
Java Doc - Interface StreamStackoverflow.com - Java 8 Distinct by property