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

相关推荐
cat三三10 分钟前
java之异常
java·开发语言
浙江第二深情15 分钟前
前端性能优化终极指南
java·maven
养乐多072231 分钟前
【Java】IO流
java
俊男无期31 分钟前
超效率工作法
java·前端·数据库
中国胖子风清扬35 分钟前
SpringAI和 Langchain4j等 AI 框架之间的差异和开发经验
java·数据库·人工智能·spring boot·spring cloud·ai·langchain
月明长歌1 小时前
【码道初阶】牛客TSINGK110:二叉树遍历(较难)如何根据“扩展先序遍历”构建二叉树?
java·数据结构·算法
用户2190326527351 小时前
Spring Boot + Redis 注解极简教程:5分钟搞定CRUD操作
java·后端
Alice1 小时前
linux scripts
java·linux·服务器
Filotimo_1 小时前
Spring Data JPA 方法名查询特性的使用
java·开发语言·windows
代码栈上的思考1 小时前
MyBatis:注解方式实现数据库 CRUD 全操作
java·开发语言·mybatis