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的Junit测试框架中的其他注解说明

    Java的Junit测试框架中的其他注解说明

    这篇文章主要介绍了Java的Junit测试框架中的其他注解说明,JUnit是一个开源的java单元测试框架,它是XUnit测试体系架架构的一种体现,
    是Java语言事实上的标准单元测试库,需要的朋友可以参考下
    2023-10-10
  • JDK(免安装)各种版本下载及配置详细图文教程

    JDK(免安装)各种版本下载及配置详细图文教程

    这篇文章主要给大家介绍了关于JDK(免安装)各种版本下载及配置的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-07-07
  • Java中ArrayList类的使用方法

    Java中ArrayList类的使用方法

    ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,下面来简单介绍下
    2013-12-12
  • SpringBoot实现列表数据导出为Excel文件

    SpringBoot实现列表数据导出为Excel文件

    这篇文章主要为大家详细介绍了在Spring Boot框架中如何将列表数据导出为Excel文件,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2024-02-02
  • mybatisPlus 大于小于的实现示例

    mybatisPlus 大于小于的实现示例

    在 MyBatis Plus 中进行条件查询,使用小于等于,大于等于操作可以通过其提供的条件构造器(Wrapper)来实现,下面就来详细的介绍一下mybatisPlus 大于小于的实现示例,感兴趣的可以了解一下
    2025-12-12
  • 深入了解JAVA 软引用

    深入了解JAVA 软引用

    这篇文章主要介绍了JAVA 软引用的相关资料,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-08-08
  • 一文带你看懂Android动画的实现原理

    一文带你看懂Android动画的实现原理

    动画是 Android 应用程序中重要的交互特性,ndroid 提供了多种动画效果,包括平移、缩放、旋转和透明度等,它们可以通过代码或 XML 来实现,本文将介绍 Android 动画的原理和实现方法,并提供一些示例,需要的朋友可以参考下
    2023-07-07
  • myeclipse创建servlet_动力节点Java学院整理

    myeclipse创建servlet_动力节点Java学院整理

    这篇文章主要为大家详细介绍了myeclipse创建servlet的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • MacBook Java开发环境搭建的详细步骤(新手必备)

    MacBook Java开发环境搭建的详细步骤(新手必备)

    本文主要介绍了MacBook Java开发环境搭建,文中通过图文示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • InputStream数据结构示例解析

    InputStream数据结构示例解析

    这篇文章主要为大家介绍了InputStream数据结构示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10

最新评论