Java 8 lambda Collectors优雅的使用方式-超详细

Jdk1.8 版本引入了lambda 表达式,对于集合操作引入了java.util.stream.Collectors官方文档中描述为:

实现各种有用的减少操作,如将元素累积到集合中,汇总根据各种标准的元素,等等。

# 那么我们来详细的看看其中的方法

初始化测试数据 

 private static void initBooks() {
        books.add(new Book("书名1", "Java", "张三", 53.2, 135, 52301L));
        books.add(new Book("书名2", "Java", "李四", 49.3D, 246, 525301L));
        books.add(new Book("书名3", "Java", "王五", 26.3D, 186, 523101L));
        books.add(new Book("书名4", "Python", "张三", 39.3D, 98, 523101L));
        books.add(new Book("书名5", "Python", "李四", 59.3D, 169, 523021L));
        books.add(new Book("书名6", "Python", "王五", 63.3D, 489, 523L));
        books.add(new Book("书名7", "C#", "张三", 72.3D, 984, 752301L));
        books.add(new Book("书名8", "C#", "李四", 48.3D, 532, 9301L));
        books.add(new Book("书名9", "C#", "王五", 47.3D, 587, 5801L));
        books.add(new Book("书名10", "Netty", "张三", 68.3D, 653, 501L));
        books.add(new Book("书名11", "Netty", "张三", 61.3D, 782, 562301L));
        books.add(new Book("书名12", "Netty", "张三", null, 698, 542301L));
    }


    @Data
    static class Book {
        /**
         * 书名
         */
        private String name;
        /**
         * 类型
         */
        private String category;
        /**
         * 作者
         */
        private String author;
        /**
         * 价格
         */
        private Double price;
        /**
         * 页数
         */
        private Integer pages;
        /**
         * 库存数量
         */
        private Long inventory;

        public Book(String name, String category, String author, Double price, Integer pages, Long inventory) {
            this.name = name;
            this.category = category;
            this.author = author;
            this.price = price;
            this.pages = pages;
            this.inventory = inventory;
        }
    }

  averagingDouble

 

    /**
     * 获取Integer/Long/Double类型的平均值
     */
    private static void testAvg() {
        //获取所有的图书的平均售价
        Double priceAvg = books.stream().collect(Collectors.averagingDouble(item -> item.getPrice() == null ? 0D : item.getPrice()));
        Optional.ofNullable(priceAvg).ifPresent(System.out::println);
        //所有图书的平均页数
        Double pageAvg = books.stream().collect(Collectors.averagingInt(item -> item.getPages() == null ? 0 : item.getPages()));
        Optional.ofNullable(pageAvg).ifPresent(System.out::println);
        //所有图书的平均库存
        Double inventoryAvg = books.stream().collect(Collectors.averagingLong(item -> item.getInventory() == null ? 0L : item.getInventory()));
        Optional.ofNullable(inventoryAvg).ifPresent(System.out::println);
    }
# averagingDouble方法返回一个Collector收集器,它生成应用于输入元素的double值函数的算术平均值。如果没有元素,则结果为0。

# 返回的平均值可能会因记录值的顺序而变化,这是由于除了不同大小的值之外,还存在累积舍入误差。
# 通过增加绝对量排序的值(即总量,样本越大,结果越准确)往往会产生更准确的结果。如果任何记录的值是NaN或者总和在任何点NaN,那么平均值将是NaN。

# 注意: double格式可以表示-253到253范围内的所有连续整数。如果管道有超过253的值,则平均计算中的除数将在253处饱和,从而导致额外的数值误差。

 collectingAndThen

 

/**
     * 现获取数据,然后再对数据进行操作
     */
    private static void testCollectingAndThen() {
        Map<String, List<Book>> upPrice = books.stream().collect(Collectors.collectingAndThen(Collectors.groupingBy(Book::getAuthor), items -> {
            items.get("张三").stream().forEach(item -> item.setPrice(item.getPrice() == null ? 0 : item.getPrice() + 10000));
            return items;
        }));

        System.out.println("按照作者分组并将张三的书籍涨价: " + upPrice);

        //根据作者分组--去除作者是张三的书籍

        Map<String, List<Book>> author = books.stream().collect(Collectors.collectingAndThen(Collectors.groupingBy(Book::getAuthor), items -> {
            items.remove("张三");
            return items;
        }));
        System.out.println("根据作者分组--去除作者是张三的书籍: " + author);

        //本次结果和上面的结果一致
        Map<String, List<Book>> collect = books.stream().filter(item -> "张三".equals(item.getAuthor())).collect(Collectors.groupingBy(Book::getAuthor));
        System.out.println(collect);
    }

 counting

 

 /**
     * 获取计数
     */
    private static void testCounting() {
        //返回所有集合的元素数量
        Long countNum = books.stream().collect(Collectors.counting());
        System.out.println(countNum);

        //如果没有任何数据的话,会返回0
        Long collect = books.stream().filter(item -> item.getAuthor().equals("11")).collect(Collectors.counting());
        System.out.println(collect);
        Long count = books.stream().filter(item -> item.getAuthor().equals("11")).count();
        System.out.println(count);
    }

groupingBy

 

/**
     * 分组
     */
    private static void testGroupBy() {
        //根据书籍种类分组
        Map<String, List<Book>> collect = books.stream().collect(Collectors.groupingBy(Book::getCategory));
        //根据书籍种类分组计数
        Map<String, Long> collect1 = books.stream().collect(Collectors.groupingBy(Book::getCategory, Collectors.counting()));
        //获取书籍种类的平均值 -默认是hashMap是无序的
        Map<String, Double> sorted = books.stream().collect(Collectors.groupingBy(Book::getCategory, Collectors.averagingDouble(item -> item.getPrice() == null ? 0 : item.getPrice())));
        System.out.println("获取书籍种类的平均值: " + sorted);
        //倒序排列-key的倒序-自定义一个比较器
        Map<String, Double> sortedTreeMapComparator = books.stream().collect(Collectors.groupingBy(Book::getCategory, () -> new TreeMap<>(Comparator.reverseOrder()), Collectors.averagingDouble((item -> item.getPrice() == null ? 0 : item.getPrice()))));
        System.out.println("获取书籍种类的平均值-倒序: " + sortedTreeMapComparator);
        //倒序排列-key的倒序-treeMp指定是降序map,调用descendingMap
        Map<String, Double> sortedTreeMap = books.stream().collect(Collectors.groupingBy(Book::getCategory, () -> new TreeMap().descendingMap(), Collectors.averagingDouble((item -> item.getPrice() == null ? 0 : item.getPrice()))));
        System.out.println("获取书籍种类的平均值-倒序: " + sortedTreeMap);

    }
# 此处需要注意,返回的Collector收集器是不支持并发的

# 当需要进行排序的时候可使用TreeMap进行排序

groupingByConcurrent

 

    /**
     * 分组能够保证线程安全
     */
    private static void testGroupByConcurrent() {
        ConcurrentMap<String, List<Book>> collect = books.stream().collect(Collectors.groupingByConcurrent(Book::getCategory));
        System.out.println("根据书籍种类进行分组: " + collect);
        ConcurrentMap<String, Long> collect1 = books.stream().collect(Collectors.groupingByConcurrent(Book::getCategory, Collectors.counting()));
        System.out.println("根据书籍种类进行分组并计算数量: " + collect1);
    }

 joining

 

 

    /**
     * 将集合元素连接成字符串
     */
    private static void testJoining() {
        //直接相连
        String authors = books.stream().map(Book::getAuthor).collect(Collectors.joining());
        System.out.println("获取作者集合字符串: " + authors);//张三李四王五张三李四王五张三李四王五张三张三张三
        //增加连接符 - distinct去除重复元素
        String authorsJoin = books.stream().map(Book::getAuthor).distinct().collect(Collectors.joining(","));
        System.out.println("获取作者集合字符串-有连接符: " + authorsJoin);//张三,李四,王五
        String collect = books.stream().map(Book::getAuthor).distinct().collect(Collectors.joining(",", "[", "]"));
        System.out.println("获取作者集合字符串-有连接符-有开始结束符号: " + collect);//[张三,李四,王五]
    }

mapping

 

 

    /**
     * 获取指定的字段或数据
     */
    private static void testMapping() {
        List<String> authors = books.stream().collect(Collectors.mapping(Book::getAuthor, Collectors.toList()));
        System.out.println("获取指定字段的集合: " + authors);//[张三, 李四, 王五, 张三, 李四, 王五, 张三, 李四, 王五, 张三, 张三, 张三]

        List<String> authorList = books.stream().map(Book::getAuthor).collect(Collectors.toList());
        System.out.println("获取指定字段的集合: " + authorList);//[张三, 李四, 王五, 张三, 李四, 王五, 张三, 李四, 王五, 张三, 张三, 张三]

        List<String> authorDistinct = books.stream().map(Book::getAuthor).distinct().collect(Collectors.toList());
        System.out.println("获取指定字段的集合: " + authorDistinct);//[张三, 李四, 王五]

    }

 maxBy

 

    /**
     * 求最大值
     */

    private static void testMaxBy() {
        //求单价最贵的书籍
        Book book1 = books.stream().collect(Collectors.maxBy((o1, o2) -> o1.getPrice() == null ? 0 : o1.getPrice()
                .compareTo(o2.getPrice() == null ? 0 : o2.getPrice()))).get();
        System.out.println("单价最贵的书籍: " + book1);

        Book book = books.stream().max((left, right) -> left.getPrice() == null ? 0 : left.getPrice()
                .compareTo(right.getPrice() == null ? 0 : right.getPrice())).get();
        System.out.println("单价最贵的书籍: " + book);
    }

minBy

 

    /**
     * 求最小值
     */
    private static void testMaxMin() {
        Book book = books.stream().min(Comparator.comparing(Book::getInventory)).get();
        System.out.println("库存最小的书籍: " + book);
        
        Book book1 = books.stream().collect(Collectors.minBy(Comparator.comparing(Book::getInventory))).get();
        System.out.println("库存最小的书籍: " + book1);
    }

partitioningBy

 

    /**
     * 根据条件分类,返回的是true和false作为key的map
     */
    private static void testPartitioningBy() {
        //查询java类别数据和非java类别数据的map集合
        Map<Boolean, List<Book>> java = books.stream().collect(Collectors.partitioningBy(item -> item.getCategory().equals("Java")));
        System.out.println("Java书籍和非Java书籍的集合: " + java);

        //平均价格
        Map<Boolean, Double> avgPrice = books.stream().collect(Collectors.partitioningBy(item -> item.getCategory().equals("Java"),
                Collectors.averagingDouble(item -> item.getPrice() == null ? 0 : item.getPrice())));
        System.out.println("java书籍和非java书籍的平均价格: " + avgPrice);

        //分类的数量
        Map<Boolean, Long> count = books.stream().collect(Collectors.partitioningBy(item -> item.getCategory().equals("Java"), Collectors.counting()));
        System.out.println("java书籍和非java书籍的书籍数量: " + count);

    }

 reducing

 

  /**
     * 各种运算
     */
    private static void testReducing() {
        //获取库存最大的书籍
        Book book = books.stream().collect(Collectors.reducing(BinaryOperator.maxBy(Comparator.comparingLong(Book::getInventory)))).get();
        System.out.println("库存最大的书籍: " + book);

        Book book1 = books.stream().reduce(BinaryOperator.maxBy(Comparator.comparingLong(Book::getInventory))).get();
        System.out.println("库存最大的书籍: " + book1);

        //获取书籍的总库存数量
        Long inventoryC = books.stream().map(Book::getInventory).reduce(0L, (left, right) -> left + right);
        System.out.println("所有书籍的库存: " + inventoryC);

        Long inventory = books.stream().map(Book::getInventory).collect(Collectors.reducing(0L, (left, right) -> left + right));
        System.out.println("所有书籍的库存: " + inventory);

        //获取所有书籍的总页数
        Integer pagesC = books.stream().collect(Collectors.reducing(0, Book::getPages, (left, right) -> left + right));
        System.out.println("所有书籍的页数总和: " + pagesC);

        Integer pages = books.stream().map(Book::getPages).collect(Collectors.reducing(0, (left, right) -> left + right));
        System.out.println("所有书籍的页数总和: " + pages);

    }

summarizingDouble

    /**
     * 求和
     */
    private static void testSummingDouble() {
        Integer pages = books.stream().collect(Collectors.summingInt(Book::getPages));
        System.out.println("所有书籍的页数总和: " + pages);

        Long inventories = books.stream().collect(Collectors.summingLong(Book::getInventory));
        System.out.println("所有书籍的库存总和: " + inventories);

        Double price = books.stream().collect(Collectors.summingDouble(item -> item.getPrice() == null ? 0D : item.getPrice()));
        System.out.println("所有书籍的单价总和: " + price);

        Double priceNotNull = books.stream().filter(item -> Objects.nonNull(item.getPrice()))
                .collect(Collectors.summingDouble(item -> item.getPrice() == null ? 0D : item.getPrice()));
        System.out.println("所有书籍的单价总和: " + priceNotNull);

    }

 toCollection

 

   /**
     * 转换成集合
     */
    private static void testToCollection() {
        //转换成set集合
        Set<Book> collect2 = books.stream().collect(Collectors.toSet());//HashSet
        Set<Book> set = books.stream().collect(Collectors.toCollection(HashSet::new));

        //
        List<Book> collect3 = books.stream().collect(Collectors.toList());//ArrayList

        LinkedList<Book> list = books.stream().collect(Collectors.toCollection(LinkedList::new));

        ArrayList<Book> collect = books.stream().collect(Collectors.toCollection(ArrayList::new));

        CopyOnWriteArrayList<Book> collect1 = books.stream().collect(Collectors.toCollection(CopyOnWriteArrayList::new));

        //toCollection可以指定转换成的集合
    }

 toConcurrentMap

 

    /**
     *支持高并发
     */
    private static void testToConcurrentMap() {

        //ConcurrentHashMap 不支持null键和null值,所以在处理的时候需要注意
        ConcurrentMap<String, Double> collect = books.stream().collect(Collectors.toConcurrentMap(Book::getName,
                item -> item.getPrice() == null ? 0 : item.getPrice()));
        System.out.println("书名和价格: " + collect);

        //出现相同的key的时候会报错-故而需要指定有相同key时候的处理策略
        ConcurrentMap<String, String> collect1 = books.stream().collect(Collectors.toConcurrentMap(Book::getAuthor,
                item -> item.getName(), (left, right) -> left));
        System.out.println("作者和书名: " + collect1);


        ConcurrentSkipListMap<String, Double> collect2 = books.stream().collect(Collectors.toConcurrentMap(Book::getAuthor,
                item -> item.getPrice() == null ? 0 : item.getPrice(), (a, b) -> a + b, ConcurrentSkipListMap::new));
        System.out.println("作者和书的单价和: " + collect2);
    }

toList

    /**
     * 转换成List
     */
    private static void testToList() {
        List<Book> collect3 = books.stream().collect(Collectors.toList());//ArrayList

        LinkedList<Book> list = books.stream().collect(Collectors.toCollection(LinkedList::new));

        ArrayList<Book> collect = books.stream().collect(Collectors.toCollection(ArrayList::new));

        CopyOnWriteArrayList<Book> collect1 = books.stream().collect(Collectors.toCollection(CopyOnWriteArrayList::new));

        //toCollection可以指定转换成的集合
    }

toMap

 

    /**
     *转换成map
     */
    private static void testToMap() {
        //调用merge的时候有空值校验,如果值为null会报空指针//HashMap
        Map<String, Double> collect = books.stream().collect(Collectors.toMap(Book::getName, item -> item.getPrice() == null ? 0 : item.getPrice()));
        System.out.println("书名和价格: " + collect);

        Map<String, String> collect1 = books.stream().collect(Collectors.toMap(Book::getAuthor, Book::getName, (one, two) -> one));//HashMap
        System.out.println("作者和书名-有重复的选择第一个书名: " + collect1);

        ConcurrentHashMap<String, String> collect2 = books.stream().collect(Collectors.toMap(Book::getAuthor, Book::getName,
                (one, two) -> one.concat(two), ConcurrentHashMap::new));
        System.out.println("作者和书名-有重复的选择第一个书名-指定返回值类型: " + collect2);
    }

toSet

 

    /**
     * 转换成Set
     */
    private static void testToSet() {
        //转换成set集合
        Set<Book> collect2 = books.stream().collect(Collectors.toSet());//HashSet
        Set<Book> set = books.stream().collect(Collectors.toCollection(HashSet::new));
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值