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

相关推荐
泡茶喝茶写代码33 分钟前
A股量化数据工程:从 REST 接口到策略信号(第 8 篇):成长能力因子:营收与利润增速
java·python·股票数据api·股票数据api接口·股票量化数据api·股票量化数据接口·股票数据api数据
\光辉岁月/1 小时前
7.javase-面向对象
java·开发语言
weixin_531094691 小时前
heap_4内存管理
java·开发语言·算法
程序员南飞2 小时前
win系统安装minio
java·数据结构·算法
Escalating_xu2 小时前
【Python】使用库:标准库、第三方库、pip、项目实战与程序打包
java·python·pip
Wang's Blog2 小时前
Java框架 SpringCloud 快速入门: 过滤器链执行顺序
java·spring cloud
砚底藏山河3 小时前
量化实战:回测数据底座快照与版本管理进阶
java·大数据·python·金融·maven
Cc.Y3 小时前
Java零基础入门:封装与继承 —— 从“裸奔“到“穿衣服“,从“重复造轮子“到“站在巨人肩膀上“
java·开发语言
Escalating_xu3 小时前
【C 语言】深入理解指针(4):回调函数、qsort、void * 与泛型排序的模拟实现
java·c语言·开发语言
Shaoshing3 小时前
雪花算法
java