Java8 Lambda - groupingBy 后再排序、累加、计数、查找...

package com.noob.testThink;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.google.common.collect.Lists;
import com.noob.json.JSON;
import lombok.Data;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;

public class GroupingByDownstreamTest {
    // @JsonFilter("ignoreVarFilter")
    @Data
    public static class Person {
        private String realName;
        // 任务类型
        private String taskType;
        private int time;
        private BigDecimal decimal;
    }

    public static void main(String[] args) {
        List<Person> list = Lists.newArrayList();
        for (int index = 0; index < 30; index++) {
            Person person = new Person();
            person.setRealName("RealName" + index % 4);
            person.setTaskType("TaskType" + index % 5);
            person.setTime(index % 6);
            person.setDecimal(new BigDecimal(person.getTime()));
            list.add(person);
        }
        // 累加的方式
        int a = list.stream().collect(Collectors.summingInt(Person::getTime));
        System.out.println(a);

        int b = list.stream().mapToInt(Person::getTime).sum();
        System.out.println(b);

        BigDecimal d = list.stream().map(Person::getDecimal).reduce(BigDecimal::add).get(); //当数据为空时这种reduce写法会报错
        System.out.println(d);

        //   list.stream().forEach(t->list.remove(t)); List和Map的stream里也不能直接remove!!! 都会expectedModCount<初始实例化迭代器就固定为当前的modCount修改次数>和modCount(remove操作会++)不一致抛出ConcurrentModificationException

        // 把list转成1:1的map.
        //  Map<String, Person> e = list.stream().collect(Collectors.toMap(Person::getRealName, Function.identity()));
        //  这里因为数据源重复问题会报错,如果想支持后覆盖前,可改写底层的mergeFunction
        /** Exception in thread "main" java.lang.IllegalStateException: Duplicate key GroupingByDownstreamTest.Person(realName=RealName0, taskType=TaskType0, time=0, decimal=0)
         at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
         at java.util.HashMap.merge(HashMap.java:1254)
         at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
         at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
         **/
        Map<String, Person> e = list.stream().collect(Collectors.toMap(Person::getRealName, Function.identity(), (k1, k2) -> k1));
        System.out.println(JSON.toJSONString(e));

        // 验证JSON动态屏蔽某个参数
        System.out.println(JSON.toJSON(list, Person.class, "realName"));

        // RealName分组并以RealName排序 (用LinkedHashMap来保存Map插入的顺序)
        Map<String, List<Person>> collect = list.stream().sorted(Comparator.comparing(Person::getRealName).reversed()).
                collect(Collectors.groupingBy(Person::getRealName, LinkedHashMap::new, Collectors.toList()));
        System.out.println(JSON.toJSONString(collect));

        //RealName分组并以Time排序
        Map<String, List<Person>> map = list.stream().collect(
                Collectors.groupingBy(Person::getRealName, HashMap::new,
                        Collectors.collectingAndThen(Collectors.toList(),
                                t -> t.stream().sorted(Comparator.comparing(Person::getTime))
                                        .collect(Collectors.toList()) )));
        System.out.println(JSON.toJSONString(map));

        List<Person> c = collect.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
        //再摊开所有的List
        System.out.println(JSON.toJSONString(c));

        // 先RealName分组 -> 只取taskType
        Map<String, List<String>> collect1 = list.stream().collect(Collectors.groupingBy(Person::getRealName,
                Collectors.mapping(Person::getTaskType, Collectors.toList())));
        System.out.println(JSON.toJSONString(collect1));

        // 先RealName分组 -> 再统计time
        Map<String, IntSummaryStatistics> collect2 = list.stream().collect(Collectors.groupingBy(Person::getRealName, Collectors.summarizingInt(Person::getTime)));
        System.out.println(JSON.toJSONString(collect2));

        Map<String, BigDecimal> collect9 = list.stream().collect(Collectors.groupingBy(Person::getRealName, Collectors.mapping(Person::getDecimal, Collectors.reducing(BigDecimal.ZERO, (x, m) -> x.add(m))))); //这种的reduce写法,在数据为空时会给默认值0进行累加
        System.out.println(JSON.toJSONString(collect9));

        // 相同key的value相加
        List<Map<String, BigDecimal>> list2 = com.google.common.collect.Lists.newArrayList(collect9, collect9);

        BinaryOperator<Map<String, BigDecimal>> mapBinaryOperator = (x, m) -> {
            x.forEach((key, value) -> m.compute(key, (key2, oldValue) -> { // Map的merge和compute很像,但merge需要传入的value不为空,否则merge会报错; 所以用compute更合适。
                if (oldValue == null) return value;
                if (value == null) return oldValue;
                return value.add(oldValue);
            }));
            return m;  // 返回最全的map
        };
        Map<String, BigDecimal> collect15 = list2.stream().reduce(mapBinaryOperator).orElse(null);
        System.out.println(JSON.toJSONString(collect15));

        // 先RealName分组 -> 再计数
        Map<String, Long> collect8 = list.stream().collect(Collectors.groupingBy(Person::getRealName, Collectors.counting()));
        System.out.println(JSON.toJSONString(collect8));

        // 先RealName分组 -> 再取最大/最小的time
        Map<String, Person> collect3 = list.stream().collect(Collectors.groupingBy(Person::getRealName,
                Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparing(Person::getTime)), Optional::get)));
        System.out.println(JSON.toJSONString(collect3));

        // RealName分组 -> TaskType分组 -> 按time排序
        Map<String, Map<String, TreeSet<Person>>> collect4 = list.stream().collect(Collectors.groupingBy(Person::getRealName,
                Collectors.groupingBy(Person::getTaskType,
                        Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<Person>(Comparator.comparing(Person::getTime)
                        )), Function.identity()))));
        System.out.println(JSON.toJSONString(collect4));

    }

}

 上例中使用了 com.fasterxml.jackson.ObjectMapper 来做JSON , 有动态忽略指定属性的示例。

/**
     * 忽略指定对象属性!  非线程安全
     *
     * @param bean 实例对象
     * @param ignoreVar 忽略属性
     * @param cla 实例对象的类class
     */
    public static String toJSON(Object bean, Class cla, String... ignoreVar) {
        /**
         * 声明式,缺点:无法动态指定
         * 1、@JsonIgnore 可以直接放在field上面表示要忽略的filed
         * 2、@JsonIgnoreProperties(value = { "id",  "firstName"}) 类级别忽略特定字段
         * 3、@JsonIgnoreType 忽略整个bean 忽略指定类型class的所有字段
         */
        FilterProvider filterProvider = new SimpleFilterProvider()
                .addFilter("ignoreVarFilter", SimpleBeanPropertyFilter.serializeAllExcept(ignoreVar)); // 定义一个过滤器ignoreVarFilter
        objectMapper.setFilters(filterProvider); // 非线程安全

        /**该过滤器要生效,可以:
         * 第一种方式: 在bean的class上指定: @JsonFilter("ignoreVarFilter") ;
         * 第二种方式: 定义一个声明过滤器ignoreVarFilter的接口,把它和实体class绑定
         */
       // objectMapper.addMixInAnnotations(cla, JsonFilterMixIn.class);

        return toJSONString(bean);
    }

    @JsonFilter("ignoreVarFilter")
    public  interface JsonFilterMixIn {}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值