Java8使用stream查找重复元素的方法示例

 更新时间:2024年04月26日 11:39:31   作者:好奇的菜鸟  
Java 8 是一个非常成功的版本,这个版本新增的Stream,配合同版本出现的Lambda ,给我们操作集合(Collection)提供了极大的便利,Stream流是JDK8新增的成员,本文给大家介绍了Java8使用stream查找重复元素的方法示例,需要的朋友可以参考下

一、查重方法

  public static <E> List<E> getDuplicateElements(List<E> list) {
        return list.stream() // list 对应的 Stream
                .collect(Collectors.toMap(e -> e, e -> 1, (a, b) -> a + b)) // 获得元素出现频率的 Map,键为元素,值为元素出现的次数
                .entrySet().stream() // 所有 entry 对应的 Stream
                .filter(entry -> entry.getValue() > 1) // 过滤出元素出现次数大于 1 的 entry
                .map(entry -> entry.getKey()) // 获得 entry 的键(重复元素)对应的 Stream
                .collect(Collectors.toList());  // 转化为 List
    }

二、测试

    public static void main(String[] args) throws Exception {
        List<String> list = Arrays.asList("a", "b", "c", "d", "a", "a", "d", "d","c","b","e","f");
        List<String> duplicateElements = getDuplicateElements(list);
 
        System.out.println("list 中重复的元素:" + duplicateElements);
    }

 运行结果

list 中重复的元素:[a, b, c, d]

拓展知识

Java8通过stream对列表去重:

1、Stream的distinct()方法

distinct()方法是Java 8中Stream提供的方法。返回的是由该流中不同元素组成的流。distinct()方法使用hashCode()和equals()方法来获取不同的元素。因此,需要去重的类必须实现hashCode()和equals()方法。也就是说,可以通过重写定制的hashCode()和equals()方法来达到特殊需求的去重。

distinct()方法声明:

Stream<T> distinct();

String列表去重

List<String> stringList = new ArrayList<String>() {{
            add("A");
            add("A");
            add("B");
            add("B");
            add("C");
        }};
        List<String> newStringList = stringList.stream().distinct().collect(Collectors.toList());
        for (String s : newStringList) {
            System.out.println(s);
        }

实体类列表去重

@Test
    public void test2() throws JsonProcessingException {
        String s = "[\n" +
                "\t{\n" +
                "        \"stuNo\": \"001\",\n" +
                "        \"name\": \"Tom\"\n" +
                "    }, {\n" +
                "        \"stuNo\": \"002\",\n" +
                "        \"name\": \"Mike\"\n" +
                "    }, {\n" +
                "        \"stuNo\": \"001\",\n" +
                "        \"name\": \"Tom\"\n" +
                "    }\n" +
                "]";
        ObjectMapper objectMapper = new ObjectMapper();
        List<Student> studentList = objectMapper.readValue(s, new TypeReference<List<Student>>() {
        });
        List<Student>  collect= studentList.stream().distinct().collect(Collectors.toList());
        System.out.println(objectMapper.writeValueAsString(collect));
 
    }

List<Object> 根据Object中某个属性去重

方式一:Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>

  @Test
    public void test3() throws JsonProcessingException {
        String s = "[\n" +
                "\t{\n" +
                "        \"stuNo\": \"001\",\n" +
                "        \"name\": \"Tom\"\n" +
                "    }, {\n" +
                "        \"stuNo\": \"002\",\n" +
                "        \"name\": \"Mike\"\n" +
                "    }, {\n" +
                "        \"stuNo\": \"001\",\n" +
                "        \"name\": \"Tom\"\n" +
                "    }\n" +
                "]";
        ObjectMapper objectMapper = new ObjectMapper();
        List<Student> studentList = objectMapper.readValue(s, new TypeReference<List<Student>>() {
        });
        List<Student>  collect= studentList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName))), ArrayList::new)
        );
        System.out.println(objectMapper.writeValueAsString(collect));
 
    }

方式二:通过filter()方法

创建一个方法作为Stream.filter()的参数,其返回值为Predicate类型,原理就是通过判断一个元素能否加入到set中。

public static void main(String[] args) {
        Person p = new Person();
        p.setName("1");
 
        Person p2 = new Person();
        p2.setName("2");
        Person p3 = new Person();
        p3.setName("1");
        List<Person> ps = new ArrayList<>();
        ps.add(p);
        ps.add(p2);
        ps.add(p3);
       
        List<Person> collect = ps.stream().filter(distinctByKey(new Function<Person, Object>() {
            @Override
            public Object apply(Person person) {
                return person.getName();
            }
        })).collect(Collectors.toList());
        System.out.println(JSON.toJSONString(collect));
    }
 
/**
 * 此方法能根据不为空的字段值去重
 * 要求person.getName()不能为空
 */
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Set<Object> seen = ConcurrentHashMap.newKeySet();
    return t -> seen.add(keyExtractor.apply(t));
}
 
/**
 * 当字段值不为空的字段值去重,为空的数据不过滤
 * person.getName()的值可为空
 *
 * @return 返回属性值为空的数据+属性值不为空且去重的数据之和
 */
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        Predicate<T> predicate = new Predicate<T>() {
            @Override
            public boolean test(T t) {
                Object o = keyExtractor.apply(t);
                if (ObjectUtils.isEmpty(o)) {
                    return true;
                }
                return seen.add(o);
            }
        };
}

到此这篇关于Java8使用stream查找重复元素的方法示例的文章就介绍到这了,更多相关Java8 stream重复元素内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java 数组越界判断和获取数组长度的实现方式

    java 数组越界判断和获取数组长度的实现方式

    这篇文章主要介绍了java 数组越界判断和获取数组长度的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 详解Spring boot使用Redis集群替换mybatis二级缓存

    详解Spring boot使用Redis集群替换mybatis二级缓存

    本篇文章主要介绍了详解Spring boot使用Redis集群替换mybatis二级缓存,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • 如何解决java:错误:无效的源发行版:17问题

    如何解决java:错误:无效的源发行版:17问题

    这篇文章主要介绍了如何解决java:错误:无效的源发行版:17问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • 从基础学java--数组

    从基础学java--数组

    数组是相同类型数据的有序集合数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们数组的声明创建
    2021-09-09
  • ToStringBuilder类的一些心得

    ToStringBuilder类的一些心得

    ToStringBuilder类的一些心得,需要的朋友可以参考一下
    2013-02-02
  • Hibernate初体验及简单错误排除代码详解

    Hibernate初体验及简单错误排除代码详解

    这篇文章主要介绍了Hibernate初体验及简单错误排除代码详解,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • springboot整合日志处理Logback的实现示例

    springboot整合日志处理Logback的实现示例

    Logback是由log4j创始人设计的又一个开源日志组件,本文主要介绍了springboot整合日志处理Logback,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-01-01
  • SpringMVC和Spring的配置文件扫描包详解

    SpringMVC和Spring的配置文件扫描包详解

    这篇文章主要介绍了SpringMVC和Spring的配置文件扫描包,本文给大家介绍的非常详细,具有一定的参考借鉴价值 ,需要的朋友可以参考下
    2019-05-05
  • JavaAgent原理及实践分享

    JavaAgent原理及实践分享

    这篇文章主要介绍了JavaAgent原理及实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • Netty分布式编码器写buffer队列逻辑剖析

    Netty分布式编码器写buffer队列逻辑剖析

    这篇文章主要介绍了Netty分布式编码器写buffer队列逻辑剖析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03

最新评论