阿里字节技术大佬都在用的List集合去重方案!

简介: 本文详解Java中List去重的多种方法,涵盖基本类型与对象去重,结合Set、Stream及重写equals/hashCode,实用性强,适合Java开发者收藏学习。

本文已收录在Github关注我,紧跟本系列专栏文章,咱们下篇再续!

  • 🚀 魔都架构师 | 全网30W技术追随者
  • 🔧 大厂分布式系统/数据中台实战专家
  • 🏆 主导交易系统百万级流量调优 & 车联网平台架构
  • 🧠 AIGC应用开发先行者 | 区块链落地实践者
  • 🌍 以技术驱动创新,我们的征途是改变世界!
  • 👉 实战干货:编程严选网

1 常规去重

除了遍历去重,常想到用Set集合不允许重复元素特点,List和Set互转去重。

// 遍历后判断赋给另一个List集合,保持原来顺序
public static void ridRepeat1(List<String> list) {
    System.out.println("list = [" + list + "]");
    List<String> listNew = new ArrayList<String>();
    for (String str : list) {
        if (!listNew.contains(str)) {
            listNew.add(str);
        }
    }
    System.out.println("listNew = [" + listNew + "]");
}
// Set集合去重,保持原来顺序
public static void ridRepeat2(List<String> list) {
    System.out.println("list = [" + list + "]");
    List<String> listNew = new ArrayList<String>();
    Set set = new HashSet();
    for (String str : list) {
        if (set.add(str)) {
            listNew.add(str);
        }
    }
    System.out.println("listNew = [" + listNew + "]");
}
// Set去重     由于Set(HashSet)的无序性,不会保持原来顺序
public static void ridRepeat3(List<String> list) {
    System.out.println("list = [" + list + "]");
    Set set = new HashSet();
    List<String> listNew = new ArrayList<String>();
    set.addAll(list);
    listNew.addAll(set);
    System.out.println("listNew = [" + listNew + "]");
}
// Set通过HashSet去重(将ridRepeat3方法缩减为一行) 无序
public static void ridRepeat4(List<String> list) {
    System.out.println("list = [" + list + "]");
    List<String> listNew = new ArrayList<String>(new HashSet(list));
    System.out.println("listNew = [" + listNew + "]");
}
// Set通过TreeSet去重   会按字典顺序重排序
public static void ridRepeat5(List<String> list) {
    System.out.println("list = [" + list + "]");
    List<String> listNew = new ArrayList<String>(new TreeSet<String>(list));
    System.out.println("listNew = [" + listNew + "]");
}
// Set通过LinkedHashSet去重  保持原来顺序
public static void ridRepeat6(List<String> list) {
    System.out.println("list = [" + list + "]");
    List<String> listNew = new ArrayList<String>(new LinkedHashSet<String>(list));
    System.out.println("listNew = [" + listNew + "]");
}

stream去重

List uniqueList = list.stream().distinct().collect(Collectors.toList());
System.out.println(uniqueList.toString());

上述方法在List元素为基本数据类型及String类型时可,但若List集合元素为对象,却失效!

List<User> userList = new ArrayList<>();
userList.add(new User(name: "小黄", age: 10));
userList.add(new User(name: "小红", age: 23));
userList.add(new User(name: "小黄", age: 78));
userList.add(new User(name: "小黄", age: 10));
// 使用HashSet,无序
Set<User> userSet = new HashSet<>(userList);
System.out.println(userSet);
// 使用LinkedHashSet,有序
List<User> listNew = new ArrayList<>(new LinkedHashSet<>(userList));
System.out.println(listNew.toString());
[User(name=小黄, age=78), User(name=小黄, age=10), User(name=小红, age=23)]
[User(name=小黄, age=10), User(name=小红, age=23), User(name=小黄, age=78)]

User 类必须正确重写 equals()hashCode() 方法,否则无法正确去重。

2 对象去重

可用for循环遍历判断去重。

2.1 stream去重

// name属性去重
List<User> uniqueNameList = userList
        .stream()
        .collect(collectingAndThen(
                toCollection(() -> new TreeSet<>(comparing(User::getName))), ArrayList::new)
        );
System.out.println("根据name去重后集合元素:" + uniqueNameList.toString());
// name,age属性去重
List<User> uniqueNameAndAgeList = userList
        .stream()
        .collect(collectingAndThen(
                toCollection(() -> new TreeSet<>(comparing(o -> o.getName() + ";" + o.getAge()))), ArrayList::new)
        );
System.out.println("根据name,age去重后集合元素:" + uniqueNameAndAgeList.toString());

输出结果:

源集合元素:[User(name=张三, age=78), User(name=李四, age=23), User(name=张三, age=10)]
有序集合元素:[User(name=张三, age=10), User(name=李四, age=23), User(name=张三, age=78)]
根据name去重后集合元素:[User(name=张三, age=10), User(name=李四, age=23)]
根据name,age去重后集合元素:[User(name=张三, age=10), User(name=张三, age=78), User(name=李四, age=23)]

重写equals()、hashCode()

@Override
public boolean equals(Object obj) {
    User user = (User) obj;
    return name.equals(user.getName()) && (age==user.getAge());
}
@Override
public int hashCode() {
    String str = name + age;
    return str.hashCode();
}
目录
相关文章
|
10月前
|
存储 Java 索引
(Python基础)新时代语言!一起学习Python吧!(二):字符编码由来;Python字符串、字符串格式化;list集合和tuple元组区别
字符编码 我们要清楚,计算机最开始的表达都是由二进制而来 我们要想通过二进制来表示我们熟知的字符看看以下的变化 例如: 1 的二进制编码为 0000 0001 我们通过A这个字符,让其在计算机内部存储(现如今,A 字符在地址通常表示为65) 现在拿A举例: 在计算机内部 A字符,它本身表示为 65这个数,在计算机底层会转为二进制码 也意味着A字符在底层表示为 1000001 通过这样的字符表示进行转换,逐步发展为拥有127个字符的编码存储到计算机中,这个编码表也被称为ASCII编码。 但随时代变迁,ASCII编码逐渐暴露短板,全球有上百种语言,光是ASCII编码并不能够满足需求
395 4
|
并行计算 Java API
Java List 集合结合 Java 17 新特性与现代开发实践的深度解析及实战指南 Java List 集合
本文深入解析Java 17中List集合的现代用法,结合函数式编程、Stream API、密封类、模式匹配等新特性,通过实操案例讲解数据处理、并行计算、响应式编程等场景下的高级应用,帮助开发者提升集合操作效率与代码质量。
562 1
|
存储 安全 Java
【Java集合类面试二十五】、有哪些线程安全的List?
线程安全的List包括Vector、Collections.SynchronizedList和CopyOnWriteArrayList,其中CopyOnWriteArrayList通过复制底层数组实现写操作,提供了最优的线程安全性能。
|
安全
List集合特有功能
List集合特有功能
221 2
|
存储 安全 Java
Java 学习路线 35 掌握 List 集合从入门到精通的 List 集合核心知识
本文详细解析Java中List集合的原理、常用实现类(如ArrayList、LinkedList)、核心方法及遍历方式,并结合数据去重、排序等实际应用场景,帮助开发者掌握List在不同业务场景下的高效使用,提升Java编程能力。
766 0
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
456 5
|
存储 分布式计算 NoSQL
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
273 3
|
NoSQL Java Redis
List集合按照由小到大排序或者由大到小排序
List集合按照由小到大排序或者由大到小排序
230 3
|
Java
用JAVA架建List集合为树形结构的代码方法
这段代码定义了一个表示树形结构的 `Node` 类和一个用于构建树形结构的 `TreeController`。`Node` 类包含基本属性如 `id`、`pid`、`name` 和 `type`,以及子节点列表 `children`。`TreeController` 包含初始化节点列表并将其转换为树形结构的方法。通过过滤和分组操作实现树形结构的构建。详情可见:[代码示例链接1](http://www.zidongmutanji.com/zsjx/43551.html),[代码效果参考链接2](https://www.257342.com/sitemap/post.html)。
409 5
|
NoSQL Java Redis
List集合按照由小到大排序或者由大到小排序
List集合按照由小到大排序或者由大到小排序
425 0