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

相关推荐
奈斯先生Vector11 分钟前
从“能调用”到“可运营”:AI Agent 进入多模型时代后的架构升级
java·javascript·数据库·人工智能·算法·架构·aigc
Json____14 分钟前
宿舍安全卫生检查系统:Node 全栈开发实战
java·前端·数据库·毕业设计·课程设计·毕设·wwwoop.com
pnoker17 分钟前
36 个驱动模块:应对协议碎片化
java·物联网·modbus·工业互联网·opc ua
码上有光18 分钟前
Linux:进程控制和进程替换
java·linux·服务器·进程控制·进程替换
默辨19 分钟前
我用Java后端的视角读了一遍JoyAgent-JDGenie
java·开发语言
SQL-First布道者25 分钟前
⚡ Spring JDBC 完整体系 · 第 5 讲 · Spring Boot Starter JDBC
java·spring boot·spring·mybatis·spring jdbc
宋哥转AI28 分钟前
深入理解 AI Agent · 多 Agent 编排 #03:Supervisor 与 Orchestrator——Dream-SaaS 双层编排架构拆解
java·人工智能·ai
木井巳32 分钟前
【JavaEE】Spring Web MVC 入门
java·spring boot·spring·servlet·java-ee
2601_9621286443 分钟前
【JavaWeb06】Tomcat基础入门:架构理解与基本配置指南
java·架构·tomcat
要开心吖ZSH44 分钟前
腾讯 IM × TRTC 联动实战:后端如何撑起一次视频问诊(混流录制篇)
java·音视频·腾讯云·健康医疗·即时通讯·im