stream流与Predicate结合对集合去重或获取重复元素

引用的所有jar包均来自于jdk自带

1.工具类

java 复制代码
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 DeduplicationUtil {
    /**
     * 去重,重复时取第一个出现的数据,自定义函数去重(采用 Predicate函数式判断,采用 Function获取比较key)
     * 内部维护一个 ConcurrentHashMap,并采用 putIfAbsent特性实现
     * 例如集合:1,1,1,2,3,4,5,5。返回:1,2,3,4,5
     * @param keyExtractor
     * @param <T>
     * @return
     */
    public 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;
    }

    /**
     * 只获取重复的数据
     * 获取多余的重复的数据(排除第一次出现的数据之后剩下的重复数据 ),
     * 例如集合:1,1,1,2,3,4,5,5。返回:1,1,5
     * @param keyExtractor
     * @param <T>
     * @return
     */
    public static <T> Predicate<T> distinctNotByKey(Function<? super T, ?> keyExtractor) {
        Map<Object,Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) != null;
    }


    /**
     * 返回所有重复对象包括第一次出现的元素
     * 例如集合:1,1,1,2,3,4,5,5。返回:1,1,1,5,5
     * 注意在如果是对象,别忘了重写其 hashCode() 和 equals() 方法。
     * @param list
     * @param function
     * @param <E>
     * @param <R>
     * @return
     */
    public static <E, R> List<E> getDuplicateElements(List<E> list, Function<E, R> function) {
        Map<R, List<E>> collect = list.stream().collect(Collectors.groupingBy(function));
        return collect.entrySet().stream()
                .filter(entry -> entry.getValue().size() > 1)
                //返回所有重复对象(包括第一次出现的元素):1,1,1,5,5
                .flatMap(entry -> entry.getValue().stream())
                //重复的集合中只返回其中一个(无论重复的元素有几个,只会返回一个):1,5
                // .map(entry -> entry.getValue().stream().findFirst().orElse(null))
                .collect(Collectors.toList());

    }
}

2.实体类对象,注意如果是对象去重,要重写hashCode() 和 equals() 方法

java 复制代码
class User {
    private String name;
    private int age;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

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

    public User() {
    }

    @Override
    public boolean equals(Object o) {

        if (Objects.equals(name, ((User)o).getName())){
            return true;
        }
        return false;
    }
    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

3.测试使用

java 复制代码
public class Test{
    public static void main(String[] args) {

        List<User> list = Arrays.asList(
                new User("小强", 11, "男"),
                new User("小玲", 15, "女"),
                new User("小虎", 23, "男"),
                new User("小虎", 26, "女"),
                new User("小飞", 19, "男"),
                new User("小 飞", 16, "未知"),
                new User("小虎", 16, "未知"),
                new User("sdfsdf", 26, "未知"),
                new User("abc", 16, null)
        );

        //去重,重复时取第一个出现的数据
        List<User> collect = list.stream().filter(DeduplicationUtil.distinctByKey(User::getName)).collect(toList());
        System.out.println(JSON.toJSONString(collect));

    }
}

打印结果:[{"age":11,"name":"小强","sex":"男"},{"age":15,"name":"小玲","sex":"女"},{"age":23,"name":"小虎","sex":"男"},{"age":19,"name":"小飞","sex":"男"},{"age":16,"name":"小 飞","sex":"未知"},{"age":26,"name":"sdfsdf","sex":"未知"},{"age":16,"name":"abc"}]

相关推荐
xiao--xin10 分钟前
Java定时任务实现方案(一)——Timer
java·面试题·八股·定时任务·timer
MrZhangBaby23 分钟前
SQL-leetcode—1158. 市场分析 I
java·sql·leetcode
一只淡水鱼6638 分钟前
【spring原理】Bean的作用域与生命周期
java·spring boot·spring原理
五味香44 分钟前
Java学习,查找List最大最小值
android·java·开发语言·python·学习·golang·kotlin
jerry-891 小时前
Centos类型服务器等保测评整/etc/pam.d/system-auth
java·前端·github
Jerry Lau1 小时前
大模型-本地化部署调用--基于ollama+openWebUI+springBoot
java·spring boot·后端·llama
小白的一叶扁舟1 小时前
Kafka 入门与应用实战:吞吐量优化与与 RabbitMQ、RocketMQ 的对比
java·spring boot·kafka·rabbitmq·rocketmq
幼儿园老大*1 小时前
【系统架构】如何设计一个秒杀系统?
java·经验分享·后端·微服务·系统架构
言之。1 小时前
【Java】面试中遇到的两个排序
java·面试·排序算法
计算机-秋大田1 小时前
基于SSM的家庭记账本小程序设计与实现(LW+源码+讲解)
java·前端·后端·微信小程序·小程序·课程设计