Java 8 Stream distinct()

Java 8 Stream distinct() method is used to remove duplicate elements from a stream of data. It returns a new stream that contains only the distinct elements according to Object.equals(Object)) of this stream.

Syntax of distinct() method

Stream<T> distinct()

Here are some examples that show how to use Java 8 Stream distinct() method.

1. Get distinct elements from a List:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class DistinctExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Alice", "Charlie", "Bob");

        List<String> distinctNames = names.stream()
                                         .distinct()
                                         .collect(Collectors.toList());

        System.out.println(distinctNames); // Output: [Alice, Bob, Charlie]
    }
}

2. Distinct elements from an array:

import java.util.Arrays;
import java.util.stream.Collectors;

public class DistinctArrayExample {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 2, 4, 5, 3, 6};

        int[] distinctNumbers = Arrays.stream(numbers)
                                      .distinct()
                                      .toArray();

        System.out.println(Arrays.toString(distinctNumbers)); // Output: [1, 2, 3, 4, 5, 6]
    }
}

3. Distinct elements with a custom object:

Suppose we have a custom class Person:

public class Person {
    private String name;
    private int age;

    // Constructors, getters, and setters
   //add equals() and hashcode() method for both fields
}

You can find distinct Person objects based on their names using distinct():

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class DistinctCustomObjectExample {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Alice", 30),
            new Person("Charlie", 35)
        );

        List<Person> distinctPeople = people.stream()
                                            .distinct()
                                            .collect(Collectors.toList());

        distinctPeople.forEach(person -> System.out.println(person.getName()));
        // Output: Alice, Bob, Charlie
    }
}

In this example, the distinct() method uses the equals() and hashCode() methods of the Person class to determine distinctness based on the name and age properties.

Note – Remember that the distinct() method depends on the implementation of the equals() and hashCode() methods in the objects being compared. Ensure that these methods are correctly implemented if you are working with custom objects.

Java 8 Stream distinct() – Miscellaneous examples

Java 8 stream example distinct by multiple fields

In Java 8, if we want to use the distinct() method with custom objects and we want to consider distinctness based on multiple fields, we can achieve this by creating a custom equals() and hashCode() implementation for our object class. Here’s an example:

Suppose we have a custom class Person with multiple fields:

import java.util.Objects;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getters and setters omitted for brevity

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
               Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

In this example, we override the equals() and hashCode() methods to consider both the name and age fields when determining object equality.

Now, let’s use the distinct() method with this custom object:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class DistinctByMultipleFieldsExample {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Alice", 30),
            new Person("Charlie", 35)
        );

        List<Person> distinctPeople = people.stream()
                                            .distinct()
                                            .collect(Collectors.toList());

        distinctPeople.forEach(person -> System.out.println(person.getName() + ", " + person.getAge()));
        // Output:
        // Alice, 30
        // Bob, 25
        // Charlie, 35
    }
}

In this example, people.stream().distinct() creates a new stream containing only the distinct Person objects, considering both the name and age fields for distinctness.

By overriding the equals() and hashCode() methods to consider the fields we want for distinctness, we can achieve distinctness based on multiple fields in our custom objects when using the distinct() method.

Few points related to Stream distinct() method.

  1. Purpose of distinct(): The distinct() method is used in Java 8 streams to remove duplicate elements from a stream. It ensures that the resulting stream contains only unique elements.
  2. Criteria for Distinctness: By default, the distinct() method relies on the equals() and hashCode() methods of the elements in the stream to determine whether elements are distinct. We can customize this behavior by overriding these methods in your custom object classes to define your own criteria for distinctness.
  3. Order Preservation: The distinct() method preserves the order of elements in the resulting stream, maintaining the original order of appearance of elements from the source stream. This behavior is particularly useful when dealing with ordered collections or arrays.
  4. Immutable Streams: The distinct() operation on a stream does not modify the original stream. Instead, it creates a new stream containing distinct elements, leaving the source stream unchanged. This aligns with the functional programming and immutability principles of Java streams.
  5. Terminal Operation: The distinct() is an intermediate operation in the Stream API. To obtain the actual result, we need to follow it with a terminal operation such as collect(), forEach(), or toList(). The terminal operation consumes the distinct elements and produces the desired output or side effect.

Understanding and correctly using the distinct() method is crucial when working with Java streams to filter and process data efficiently while ensuring uniqueness.

Ten objective questions related to the Java 8 Stream distinct() method.

Question 1: What is the purpose of the distinct() method in Java 8 streams?

a) To sort elements in a stream.
b) To find the maximum element in a stream.
c) To remove duplicate elements from a stream.
d) To filter elements in a stream.

Question 2: Which interface in Java represents a stream of elements?

a) List
b) Stream
c) Collection
d) Array

Question 3: What kind of elements can be used with the distinct() method in a stream?

a) Only primitive data types (e.g., int, double)
b) Only custom objects
c) Any type of elements
d) Only strings

Question 4: What is the return type of the distinct() method?

a) List
b) Stream
c) Set
d) Array

Question 5: Which method is used to collect the distinct elements from a stream into a list or another collection?

a) collect()
b) distinct()
c) filter()
d) map()

Question 6: How does the distinct() method determine whether elements are distinct in a stream?

a) It relies on the natural order of elements.
b) It uses a provided comparator.
c) It uses the equals() and hashCode() methods of the elements.
d) It removes elements randomly.

Question 7: What happens when the distinct() method is applied to a stream containing duplicate elements?

a) It throws a compile-time error.
b) It removes all elements from the stream.
c) It retains only the distinct elements in the resulting stream.
d) It creates a new stream with all the elements unchanged.

Question 8: Which of the following is a terminal operation that can be used with a stream after applying distinct() to collect distinct elements?

a) map()
b) filter()
c) reduce()
d) collect()

Question 9: In a stream of custom objects, how can you specify the criteria for distinctness when using the distinct() method?

a) Need to override the equals() and hashCode() methods in your custom object class.
b) By providing a custom comparator as an argument to distinct().
c) By using the filter() method before distinct().
d) It is not possible to specify custom distinctness criteria.

Answers:

  1. c) To remove duplicate elements from a stream.
  2. b) Stream
  3. c) Any type of elements
  4. b) Stream
  5. a) collect()
  6. c) It uses the equals() and hashCode() methods of the elements.
  7. c) It retains only the distinct elements in the resulting stream.
  8. d) collect()
  9. b) Need to override the equals() and hashCode() methods in your custom object class.

That’s all about the Java 8 Stream distinct() method.

See docs.

Other Java 8 Stream Examples.