Java Stream去重详解

Stream是Java 8引入的一款新特性,它支持函数式编程,可以使用Lambda表达式来对集合进行操作,使代码更简洁、优雅。而去重是Stream中常见的操作之一,那么Stream如何去重呢?本文将从多个方面对Stream去重做详细的阐述。

一、Stream去重字段

如果我们要对一个对象的某个字段进行去重,可以使用Stream的distinct()方法来实现。例如我们有一个Person对象,包含id和name两个属性,我们要根据name来去重:


List<Person> list = getList();
list.stream().map(Person::getName).distinct().forEach(System.out::println);

在上述代码中,我们首先将List转换为Stream,然后使用map方法获取每个Person对象的name属性,使用distinct()方法来去重,最后使用forEach打印每个不同的name。

二、Stream去重list元素方法

如果我们需要对一个List对象的元素进行去重,可以使用Stream的distinct()方法结合Collector的toCollection()方法来实现。例如我们有一个List<Integer>对象,要对其中的元素进行去重:


List<Integer> list = Arrays.asList(1, 2, 3, 1, 2, 4);
List<Integer> distinctList = list.stream().distinct().collect(Collectors.toCollection(ArrayList::new));
System.out.println(distinctList);

在上述代码中,我们首先将List转换为Stream,然后使用distinct()方法来去重,最后使用Collector的toCollection()方法将结果转换为ArrayList。

三、Stream去重源码

如果我们需要查看Stream去重的源码,可以查看Java API文档,或者在IDE中进入Stream的distinct()方法进行查看。以下是官方API对distinct()方法的定义:


default Stream<T> distinct() {
    return this.<T, T, HashSet<T>>collect(Collectors.toSet()).stream();
}

可以看到,stream的distinct()方法实际上是调用了Collectors.toSet()方法来生成一个HashSet对象,然后再将HashSet转换为Stream对象。

四、Stream去重的四种方法

除了使用distinct()方法来进行去重外,我们还有其他几种方法可以实现Stream的去重:

1.使用HashSet去重

我们可以使用HashSet对象来进行Stream的去重,其实现逻辑与distinct()方法类似:


List<Person> list = getList();
List<Person> distinctList = new ArrayList<>(new HashSet<>(list));
System.out.println(distinctList);

2.使用TreeSet去重

我们还可以使用TreeSet对象来进行Stream的去重,其可以根据元素的自然排序进行去重:


List<Integer> list = Arrays.asList(1, 2, 3, 1, 2, 4);
List<Integer> distinctList = new ArrayList<>(new TreeSet<>(list));
System.out.println(distinctList);

3.使用HashMap去重

我们可以使用HashMap来进行Stream的去重,其利用Object的hashCode()和equals()方法来判断元素是否重复:


List<String> list = Arrays.asList("apple", "banana", "orange", "banana", "pear");
List<String> distinctList = new ArrayList<>(new HashMap<>().values());
System.out.println(distinctList);

4.使用Stream.collect(Collectors.groupingBy())方法去重

我们还可以使用groupingBy()方法来进行Stream的去重,其利用Map的键的唯一性来去重:


List<String> list = Arrays.asList("apple", "banana", "orange", "banana", "pear");
List<String> distinctList = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
                .entrySet().stream().filter(entry -> entry.getValue() == 1L).map(Map.Entry::getKey)
                .collect(Collectors.toList());
System.out.println(distinctList);

五、Stream去重的字段获取

在使用Stream进行去重时,我们需要注意获取去重字段。如果是List对象,则可以直接获取每个对象,如果是Map对象,则需要获取Map中的value,并转换为List对象;如果是对象集合,则需要获取对象属性,例如:


List<Person> list = getList();
List<String> nameList = list.stream().map(Person::getName).distinct().collect(Collectors.toList());

在上述代码中,我们首先将List转换为Stream,然后使用map方法获取每个Person对象的name属性,使用distinct()方法来去重,最后使用Collectors.toList()方法将去重结果转换为List对象。

六、Stream去重保留最后一条

有时候我们需要对重复元素进行去重,但是保留最后一条元素,可以使用Stream的collect()方法来实现:


List<Person> list = getList();
List<Person> distinctList = list.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName).reversed())),
                ArrayList::new));
System.out.println(distinctList);

在上述代码中,我们使用Comparator.comparing()方法来根据name属性逆序排序,然后使用collectingAndThen()方法来将去重结果转换为ArrayList。

七、Stream去重后分组排序

如果我们需要对去重后的元素进行分组排序,可以先进行去重,然后再使用Stream的sorted()方法来实现分组排序:


List<Person> list = getList();
List<Person> distinctList = list.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName).reversed())),
                ArrayList::new));
Map<String, List<Person>> groupMap = distinctList.stream().sorted((p1, p2) -> p2.getAge() - p1.getAge())
                .collect(Collectors.groupingBy(Person::getName));
System.out.println(groupMap);

在上述代码中,我们首先使用collectingAndThen()方法将去重结果转换为ArrayList,然后使用sorted()方法按照age属性对去重后的元素进行逆序排序,最后使用groupingBy()方法进行分组。

八、Stream去重复后limit返回

如果我们只需要去重后的前几个元素,可以使用limit()方法来限制返回数量:


List<Person> list = getList();
List<Person> distinctList = list.stream().distinct().limit(3).collect(Collectors.toList());
System.out.println(distinctList);

在上述代码中,我们使用limit()方法限制去重后的元素数为3,并使用toList()方法将结果转换为List对象。

九、Stream去重根据多个条件

如果我们是需要根据多个属性进行去重,可以使用distinct()方法结合Comparator来实现。例如我们有一个Person对象,包含id、name和age三个属性,我们要根据name和age来去重:


List<Person> list = getList();
List<Person> distinctList = list.stream().distinct().sorted(
                Comparator.comparing(Person::getName).thenComparingInt(Person::getAge))
                .collect(Collectors.toList());
System.out.println(distinctList);

在上述代码中,我们首先使用distinct()方法去重,然后使用sorted()方法按照name和age属性进行排序,最后使用Collectors.toList()方法将结果转换为List对象。

结语

通过本文的介绍,我们已经掌握了Stream的去重操作,包括使用distinct()方法、HashSet、TreeSet、HashMap、groupingBy()方法、collect()方法等多种方式,同时还介绍了多属性排序、限制返回数量等高级用法。希望本文能帮助大家更好地使用Stream进行开发。

原创文章,作者:RCPXA,如若转载,请注明出处:https://www.506064.com/n/369148.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
RCPXARCPXA
上一篇 2025-04-12 13:00
下一篇 2025-04-12 13:00

相关推荐

  • java client.getacsresponse 编译报错解决方法

    java client.getacsresponse 编译报错是Java编程过程中常见的错误,常见的原因是代码的语法错误、类库依赖问题和编译环境的配置问题。下面将从多个方面进行分析…

    编程 2025-04-29
  • Java JsonPath 效率优化指南

    本篇文章将深入探讨Java JsonPath的效率问题,并提供一些优化方案。 一、JsonPath 简介 JsonPath是一个可用于从JSON数据中获取信息的库。它提供了一种DS…

    编程 2025-04-29
  • Java腾讯云音视频对接

    本文旨在从多个方面详细阐述Java腾讯云音视频对接,提供完整的代码示例。 一、腾讯云音视频介绍 腾讯云音视频服务(Cloud Tencent Real-Time Communica…

    编程 2025-04-29
  • Java Bean加载过程

    Java Bean加载过程涉及到类加载器、反射机制和Java虚拟机的执行过程。在本文中,将从这三个方面详细阐述Java Bean加载的过程。 一、类加载器 类加载器是Java虚拟机…

    编程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介绍

    本文将详细介绍Java Milvus SearchParam withoutFields的相关知识和用法。 一、什么是Java Milvus SearchParam without…

    编程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java语言中的一个版本,于2014年3月18日发布。本文将从多个方面对Java 8中某一周的周一进行详细的阐述。 一、数组处理 Java 8新特性之一是Stream…

    编程 2025-04-29
  • Java判断字符串是否存在多个

    本文将从以下几个方面详细阐述如何使用Java判断一个字符串中是否存在多个指定字符: 一、字符串遍历 字符串是Java编程中非常重要的一种数据类型。要判断字符串中是否存在多个指定字符…

    编程 2025-04-29
  • VSCode为什么无法运行Java

    解答:VSCode无法运行Java是因为默认情况下,VSCode并没有集成Java运行环境,需要手动添加Java运行环境或安装相关插件才能实现Java代码的编写、调试和运行。 一、…

    编程 2025-04-29
  • Java任务下发回滚系统的设计与实现

    本文将介绍一个Java任务下发回滚系统的设计与实现。该系统可以用于执行复杂的任务,包括可回滚的任务,及时恢复任务失败前的状态。系统使用Java语言进行开发,可以支持多种类型的任务。…

    编程 2025-04-29
  • Java 8 Group By 会影响排序吗?

    是的,Java 8中的Group By会对排序产生影响。本文将从多个方面探讨Group By对排序的影响。 一、Group By的概述 Group By是SQL中的一种常见操作,它…

    编程 2025-04-29

发表回复

登录后才能评论