介绍
java8 中 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:
* <pre>{@code
* List<String> people
* = people.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));
* }</pre>
*
* @param <T> the type of the input elements
* @param <A> intermediate accumulation type of the downstream collector
* @param <R> result type of the downstream collector
* @param <RR> 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<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
Function<R,RR> finisher) {
Set<Collector.Characteristics> 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函数的帮助下执行附加的转换步骤。
实现
package com.onway.fortunes.shop.tests;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
/***
* @Author yhj
* @Date 2021/9/15 0015 上午 10:59
*/
@Data
@AllArgsConstructor
public class UserInfo {
@ApiModelProperty("姓名")
private String name;
@ApiModelProperty("课程")
private String course;
@ApiModelProperty("分数")
private Integer grade;
}
package com.onway.fortunes.shop.tests;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.*;
import java.util.stream.Collectors;
/***
* @Author yhj
* @Date 2021/9/15 0015 上午 10:57
*/
@Slf4j
public class RemoveRepeatTest extends BaseTest {
private List<UserInfo> getUserList() {
List<UserInfo> list = new ArrayList<>();
UserInfo zhangsan_sx = new UserInfo("zhangsan", "数学", 60);
UserInfo zhangsan_yw = new UserInfo("zhangsan", "语文", 70);
UserInfo zhangsan_yy = new UserInfo("zhangsan", "英语", 70);
UserInfo zhangsan_yy_2 = new UserInfo("zhangsan", "英语", 80);
UserInfo lisi_sx = new UserInfo("lisi", "数学", 60);
UserInfo lisi_yw = new UserInfo("lisi", "语文", 70);
UserInfo lisi_yw_2 = new UserInfo("lisi", "语文", 80);
UserInfo wangwu_yy = new UserInfo("wangwu", "英语", 70);
UserInfo wangwu_yy_2 = new UserInfo("wangwu", "英语", 90);
list.add(zhangsan_sx);
list.add(zhangsan_yw);
list.add(zhangsan_yy);
list.add(zhangsan_yy_2);
list.add(lisi_sx);
list.add(lisi_yw);
list.add(lisi_yw_2);
list.add(wangwu_yy);
list.add(wangwu_yy_2);
return list;
}
@Test
public void userList() {
List<UserInfo> userList = getUserList();
log.info("[userList] userList = {}", JSON.toJSONString(userList));
// 获取集合内每个人出现的次数
Map<String, Long> counting = userList.stream().collect(
Collectors.groupingBy(
UserInfo::getName, Collectors.counting()
)
);
log.info("[userList] counting = {}", JSON.toJSONString(counting));
// 根据姓名去重(单字段去重)
List<UserInfo> singleField = userList.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(
Comparator.comparing(UserInfo::getName)
)
), ArrayList::new
)
);
log.info("[userList] singleField = {}", JSON.toJSONString(singleField));
// 根据姓名、学科去重(多字段去重)
ArrayList<UserInfo> multiField = userList.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(
Comparator.comparing(
e -> e.getName()
+ ";"
+ e.getCourse()
)
)
), ArrayList::new
)
);
log.info("[userList] multiField = {}", JSON.toJSONString(multiField));
// 查找分数最高 姓名与得分
String highestScore = userList.stream().collect(
Collectors.collectingAndThen(
Collectors.maxBy(
Comparator.comparing(
UserInfo::getCourse
)
), (
Optional<UserInfo> userInfo
) -> userInfo.map(e -> e.getName()
+ " : "
+ e.getCourse()
).orElse(null)
)
);
log.info("[userList] highestScore = {}", highestScore);
// 计算平均分
Integer average = userList.stream().collect(
Collectors.collectingAndThen(
Collectors.averagingInt(
UserInfo::getGrade
), Double::intValue
)
);
log.info("[userList] average = {}", average);
}
}
输出
[userList] userList = [{"course":"数学","grade":60,"name":"zhangsan"},{"course":"语文","grade":70,"name":"zhangsan"},{"course":"英语","grade":70,"name":"zhangsan"},{"course":"英语","grade":80,"name":"zhangsan"},{"course":"数学","grade":60,"name":"lisi"},{"course":"语文","grade":70,"name":"lisi"},{"course":"语文","grade":80,"name":"lisi"},{"course":"英语","grade":70,"name":"wangwu"},{"course":"英语","grade":90,"name":"wangwu"}]
[userList] counting = {"lisi":3,"zhangsan":4,"wangwu":2}
[userList] singleField = [{"course":"数学","grade":60,"name":"lisi"},{"course":"英语","grade":70,"name":"wangwu"},{"course":"数学","grade":60,"name":"zhangsan"}]
[userList] multiField = [{"course":"数学","grade":60,"name":"lisi"},{"course":"语文","grade":70,"name":"lisi"},{"course":"英语","grade":70,"name":"wangwu"},{"course":"数学","grade":60,"name":"zhangsan"},{"course":"英语","grade":70,"name":"zhangsan"},{"course":"语文","grade":70,"name":"zhangsan"}]
[userList] highestScore = zhangsan : 语文
[userList] average = 72