zoukankan      html  css  js  c++  java
  • 用Collectors对List去重

    在学习本篇之前,最好对java8新特性有一定的了解。可以参考:Java8新特性--流(Stream)

    场景:有一个实体的List集合,需要根据实体中的某个字段对List去重

    要想去重,可以考虑使用TreeSet。先来看看TreeSet的用法:

    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public class Dish {
        
        private String id;
        
        private String name;
    
    }
       private static List<Dish> dishList = new ArrayList<Dish>();
    
        static {
            Dish dish1 = new Dish("001", "张三");
            dishList.add(dish1);
            Dish dish2 = new Dish("001", "李四");
            dishList.add(dish2);
            Dish dish3 = new Dish("002", "王五");
            dishList.add(dish3);
        }
        /**
         * 测试TreeSet默认比较器及传入比较器
         */
        @Test
        public void testTreeSet() {
            // TreeSet不传比较器,则默认按照自然顺序排序
            TreeSet<Integer> treeSet = new TreeSet<>();
            treeSet.add(3);
            treeSet.add(1);
            treeSet.add(4);
            System.out.println(treeSet);
            // [1, 3, 4]
    
            // TreeSet中的元素,如果是实体,必须得传比较器(或者实体类需要实现Comparable中的compareTo方法),不然就会报错
            // TreeSet是Set的子类,里面的元素有序且不能重复,可以去重
            TreeSet<Dish> treeSet2 = new TreeSet<>(Comparator.comparing(Dish::getId));
            treeSet2.addAll(dishList);
            treeSet2.forEach(d -> System.out.println("id:" + d.getId() + ", name:" + d.getName()));
            // id:001, name:张三
            // id:002, name:王五
        }

    从上面可以看到TreeSet可以根据实体中的某个字段(这里是id)排序后去重。如果再将TreeSet转为List就可以达到我们的目的:

         List<Dish> newDishList = new ArrayList<>(treeSet2);
            newDishList.forEach(d -> System.out.println("id:" + d.getId() + ", name:" + d.getName()));
            // id:001, name:张三
            // id:002, name:王五

    虽然大功告成,但是写这么一堆代码,好麻烦。可以使用java8中的收集器简化一下:

      /**
         * 测试Collectors.toCollection方法:将结果收集到其它类型的集合中(这里是TreeSet)
         */
        @Test
        public void testToCollection() {
            TreeSet<Dish> treeSet2 = dishList.stream()
                    .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Dish::getId))));
            List<Dish> newDishList = new ArrayList<>(treeSet2);
            newDishList.forEach(d -> System.out.println("id:" + d.getId() + ", name:" + d.getName()));
            // id:001, name:张三
            // id:002, name:王五
        }

    还可以再简单一点:

      /**
         * 测试Collectors.collectingAndThen方法:将流中的数据通过Collector计算,计算的结果再通过Function处理一下
         * (这里是将TreeSet转为ArrayList。即相当于将最终结果又经过了new ArrayList<>(treeSet))
         */
        @SuppressWarnings("unchecked")
        @Test
        public void testCollectingAndThen() {
            List<Dish> newDishList = dishList.stream().collect(Collectors.collectingAndThen(
                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Dish::getId))), ArrayList::new));
            newDishList.forEach(d -> System.out.println("id:" + d.getId() + ", name:" + d.getName()));
            // id:001, name:张三
            // id:002, name:王五
        }

      

  • 相关阅读:
    pandas DataFrame
    pandas Series
    numpy nan和inf
    Filder配置及使用教程
    Vmware Ubuntu18.04更换清华源
    numpy 其它常用方法
    numpy 数组的拼接
    numpy 数值的修改
    numpy 索引和切片
    class 绑定的数据对象不必内联定义在模板里
  • 原文地址:https://www.cnblogs.com/xuwenjin/p/9660393.html
Copyright © 2011-2022 走看看