java8 Stream 通过distinct()进行去重

551 阅读2分钟

介绍

java8 Stream 提供的distinct()功能用于对流中的多个元素进行去重处理,并返回由不同元素组成的流。

stream.distinct对List<String>去重

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

public class StreamDistinctDemo {
    public static void main(String[] args) {
        String[] strArr = new String[]{"aaa", "bbb", "ccc", "aac", "bbb", "aac"};
        List<String> stringList = Arrays.asList(strArr);
        System.out.println("List<String> 的情况——去重操作之前:" + stringList);
        stringList = stringList.stream().distinct().collect(Collectors.toList());
        System.out.println("List<String> 的情况——去重操作之后:" + stringList);
    }
}

执行结果:

List<String> 的情况——去重操作之前:[aaa, bbb, ccc, aac, bbb, aac]
List<String> 的情况——去重操作之后:[aaa, bbb, ccc, aac]

stream.distinct对List<Integer>去重

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

public class StreamDistinctDemo {
    public static void main(String[] args) {
        Integer[] intArr = new Integer[]{1, 4, 2, 5, 2, 5, 8, 2, 9};
        List<Integer> integerList = Arrays.asList(intArr);
        System.out.println("List<Integer> 的情况——去重操作之前:" + integerList);
        integerList = integerList.stream().distinct().collect(Collectors.toList());
        System.out.println("List<Integer> 的情况——去重操作之后:" + integerList);
    }
}

执行结果:

List<Integer> 的情况——去重操作之前:[1, 4, 2, 5, 2, 5, 8, 2, 9]
List<Integer> 的情况——去重操作之后:[1, 4, 2, 5, 8, 9]

stream.distinct对List<Object>去重

distinct()使用Object的 equals() 方法判断元素是否重复。

Object.equals() 通过判断两个对象是否引用同一个地址来判定是否相等。

基于以上,当我们需要对Class 对象进行distinct时,需要进行重写equals()方法。

但是,equals()重写时hashCode()必须重写,所以类的hashCode()方法也必须重写。

定义类

class Person {
    String name;
    int age;

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

    @Override
    public String toString() {
        return String.format(java.util.Locale.ROOT, "[%s, %d]", this.name, this.age);
    }

    @Override
    public boolean equals(final Object obj) {
        if (obj == null) {
            return false;
        }
        final Person person = (Person) obj;
        if (this == person) {
            return true;
        } else {
            return (this.name.equals(person.name) && this.age == person.age);
        }
    }

    @Override
    public int hashCode() {
        int hashno = 7;
        hashno = 13 * hashno + (name == null ? 0 : name.hashCode()) + age;
        return hashno;
    }
}

去重操作

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

public class StreamDistinctDemo {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("aa", 18));
        personList.add(new Person("bb", 19));
        personList.add(new Person("aa", 18));
        personList.add(new Person("aa", 19));
        System.out.println("List<Person> 的情况——去重操作之前:" + personList);
        List<Person> personList1 = personList.stream().distinct().collect(Collectors.toList());
        System.out.println("List<Person> 的情况——去重操作之后:" + personList1);
    }
}

执行结果:

List<Person> 的情况——去重操作之前:[[aa, 18], [bb, 19], [aa, 18], [aa, 19]]
List<Person> 的情况——去重操作之后:[[aa, 18], [bb, 19], [aa, 19]]

基于Class属性对Object去重

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;
import java.util.stream.Collectors;

public class StreamDistinctDemo {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("aa", 18));
        personList.add(new Person("bb", 19));
        personList.add(new Person("aa", 18));
        personList.add(new Person("aa", 19));
        System.out.println("List<Person> 的情况——去重操作之前:" + personList);
        List<Person> personList1 = personList.stream().filter(distinctByKey(d->d.name)) .collect(Collectors.toList());
        System.out.println("List<Person> 的情况——去重操作之后:" + personList1);
    }

    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;
    }
}

执行结果:

List<Person> 的情况——去重操作之前:[[aa, 18], [bb, 19], [aa, 18], [aa, 19]]
List<Person> 的情况——去重操作之后:[[aa, 18], [bb, 19]]