java8 Collectors.collectingAndThen 常用用法

  

   学习了groupingBy的用法,里面经常会用到 Collectors.collectingAndThen,我理解为后续操作。

JDK源码

java.util.stream.Collectors#collectingAndThen方法的作用是将Collector的结果在执行一个额外的finisher转换操作,其源码如下:

/**
 * Adapts a {@code Collector} to perform an additional finishing
 * transformation.  For example, one could adapt the {@link #toList()}
 * collector to always produce an immutable list with:
 * 
{@code
 *     List people
 *         = people.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));
 * }
 *  * @param the type of the input elements  * @param intermediate accumulation type of the downstream collector  * @param result type of the downstream collector  * @param result type of the resulting collector  * @param downstream a collector  * @param finisher a function to be applied to the final result of the downstream collector  * @return a collector which performs the action of the downstream collector,  * followed by an additional finishing step  */ public static Collector collectingAndThen(Collector downstream, Function finisher) {     Set characteristics = downstream.characteristics();     if (characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) {         if (characteristics.size() == 1) {             characteristics = Collectors.CH_NOID;         } else {             characteristics = EnumSet.copyOf(characteristics);             characteristics.remove(Collector.Characteristics.IDENTITY_FINISH);             characteristics = Collections.unmodifiableSet(characteristics);         }     }     return new CollectorImpl<>(downstream.supplier(),             downstream.accumulator(),             downstream.combiner(),             downstream.finisher().andThen(finisher),             characteristics); }


T:输入元素的类型
A:下游Collector的中间堆积类型
R:下游Collector的结果类型
RR:结果Collector的结果类型
参数:此方法接受下面列出的两个参数

downstream: Collector的一个实例,可以使用任何Collector
finisher: 类型是Function,该函数将应用于下游Collector的最终结果
返回值:返回一个执行下游Collector动作的Collector,然后在finisher函数的帮助下执行附加的转换步骤。

使用:

模拟数据:

 public static JSONArray initData(){
        String data = "[{\"code\":\"4\",\"codeType\":\"ALRAM\",\"sortId\":\"4\",\"name\":\"特级告警\"},{\"code\":\"2\",\"codeType\":\"ALRAM\",\"sortId\":\"2\",\"name\":\"中级告警\"},{\"code\":\"3\",\"codeType\":\"ALRAM\",\"sortId\":\"3\",\"name\":\"严重告警\"},{\"code\":\"1\",\"codeType\":\"ALRAM\",\"sortId\":\"1\",\"name\":\"普通告警\"},{\"code\":\"2\",\"codeType\":\"NOTICE\",\"sortId\":\"2\",\"name\":\"邮箱通知\"},{\"code\":\"1\",\"codeType\":\"NOTICE\",\"sortId\":\"1\",\"name\":\"短信通知\"},{\"code\":\"3\",\"codeType\":\"NOTICE\",\"sortId\":\"3\",\"name\":\"微信消息通知\"}]";
        return JSON.parseArray(data);
    }

toList

获取字段类型的各名称

  public static void main(String[] args){
        JSONArray items = initData();
        Map> codeTypeNameMap1 = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e)
                .collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"), Collectors
                        .collectingAndThen(Collectors.toList(),
                                t -> ListUtils.emptyIfNull(t).stream().map(x -> MapUtils.getString(x, "name"))
                                        .filter(Objects::nonNull).distinct().collect(Collectors.toList()))));
        System.out.println(JSON.toJSONString(codeTypeNameMap1));

    }

结果:

{
	"NOTICE": ["邮箱通知", "短信通知", "微信消息通知"],
	"ALRAM": ["特级告警", "中级告警", "严重告警", "普通告警"]
}

不过这种写法会有点繁琐,使用mapping更为简便直观:

Map> codeTypeNameMap2 = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e)
.collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),
Collectors.mapping(f1 -> MapUtils.getString(f1, "name"), Collectors.toList())));
        System.out.println(JSON.toJSONString(codeTypeNameMap2));

toMap

获取字段类型的字典及其名称

 public static void main(String[] args){
        JSONArray items = initData();
        Map> codeTypeMap1 = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e)
.collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"), 
Collectors.collectingAndThen(Collectors.toMap(f1 -> MapUtils.getString(f1, "code"),
  f2 -> MapUtils.getString(f2, "name"), (x, y) -> x), v -> v)));
        System.out.println(JSON.toJSONString(codeTypeMap1));

    }

结果:

{
	"NOTICE": {
		"1": "短信通知",
		"2": "邮箱通知",
		"3": "微信消息通知"
	},
	"ALRAM": {
		"1": "普通告警",
		"2": "中级告警",
		"3": "严重告警",
		"4": "特级告警"
	}
}

这个直接用toMap的方式也更为简便直观

Map> codeTypeMap2 = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e)
                .collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),
                Collectors.toMap(f1 -> MapUtils.getString(f1, "code"),
                                f2 -> MapUtils.getString(f2, "name"), (x, y) -> x)));
        System.out.println(JSON.toJSONString(codeTypeMap2));

maxBy

分组后找到code最大的内容

public static void main(String[] args){
        JSONArray items = initData();
        Map codeMax = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e)
       .collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),
 Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(f1 -> MapUtils.getInteger(f1, "code"))), Optional::get)));

        System.out.println(JSON.toJSONString(codeMax));
    }

结果:

{
	"NOTICE": {
		"code": "3",
		"codeType": "NOTICE",
		"sortId": "3",
		"name": "微信消息通知"
	},
	"ALRAM": {
		"code": "4",
		"codeType": "ALRAM",
		"sortId": "4",
		"name": "特级告警"
	}
}

这个可以直接用toMap和BinaryOperator.maxBy进行处理

public static void main(String[] args){
        JSONArray items = initData();
        Map codeMax = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e)
                .collect(Collectors.toMap(e -> MapUtils.getString(e, "codeType"),
                        Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(f1 -> MapUtils.getInteger(f1, "code")))));

        System.out.println(JSON.toJSONString(codeMax));
    }

sort asc

分组后,根据sortId进行排序-正序

 public static void main(String[] args){
        JSONArray items = initData();
        Map> groupAscSort = ListUtils.emptyIfNull(items).stream()
                .map(e -> (JSONObject) e)
   .collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),
                        LinkedHashMap::new,
     Collectors.collectingAndThen(Collectors.toList(), s ->
                                s.stream().sorted(Comparator.comparing(e -> e.getInteger("sortId"))).collect(Collectors.toList()))));
        System.out.println(JSON.toJSONString(groupAscSort));
    }

结果:

{
	"ALRAM": [{
		"code": "1",
		"codeType": "ALRAM",
		"sortId": "1",
		"name": "普通告警"
	}, {
		"code": "2",
		"codeType": "ALRAM",
		"sortId": "2",
		"name": "中级告警"
	}, {
		"code": "3",
		"codeType": "ALRAM",
		"sortId": "3",
		"name": "严重告警"
	}, {
		"code": "4",
		"codeType": "ALRAM",
		"sortId": "4",
		"name": "特级告警"
	}],
	"NOTICE": [{
		"code": "1",
		"codeType": "NOTICE",
		"sortId": "1",
		"name": "短信通知"
	}, {
		"code": "2",
		"codeType": "NOTICE",
		"sortId": "2",
		"name": "邮箱通知"
	}, {
		"code": "3",
		"codeType": "NOTICE",
		"sortId": "3",
		"name": "微信消息通知"
	}]
}

sort desc

分组后,根据sortId进行排序-反序

public static void main(String[] args){
        JSONArray items = initData();
        Map> groupReverseSort = ListUtils.emptyIfNull(items).stream()
                .map(e -> (JSONObject) e)
                .collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),
                        LinkedHashMap::new,
   Collectors.collectingAndThen(Collectors.toList(), s ->
               s.stream().sorted((c1, c2) ->
    MapUtils.getInteger(c2, "sortId").compareTo(MapUtils.getInteger(c1, "sortId"))).collect(Collectors.toList()))));
        System.out.println(JSON.toJSONString(groupReverseSort));
    }

结果:

{
	"ALRAM": [{
		"code": "4",
		"codeType": "ALRAM",
		"sortId": "4",
		"name": "特级告警"
	}, {
		"code": "3",
		"codeType": "ALRAM",
		"sortId": "3",
		"name": "严重告警"
	}, {
		"code": "2",
		"codeType": "ALRAM",
		"sortId": "2",
		"name": "中级告警"
	}, {
		"code": "1",
		"codeType": "ALRAM",
		"sortId": "1",
		"name": "普通告警"
	}],
	"NOTICE": [{
		"code": "3",
		"codeType": "NOTICE",
		"sortId": "3",
		"name": "微信消息通知"
	}, {
		"code": "2",
		"codeType": "NOTICE",
		"sortId": "2",
		"name": "邮箱通知"
	}, {
		"code": "1",
		"codeType": "NOTICE",
		"sortId": "1",
		"name": "短信通知"
	}]
}

总结:

    Collectors.collectingAndThen除了排序的,另外其它都直接替换。但是也要熟悉,这样当遇到需要进一步处理数据,也不知道有更简便的方法的时候,就可以直接用 collectingAndThen的方式去写。再不行,就分两步写。

你可能感兴趣的:(Java8,java8,AndThen)