return new CollectorImpl<CharSequence, StringBuilder, String>(
StringBuilder::new, StringBuilder::append,
(r1, r2) -> { r1.append(r2); return r1; },
StringBuilder::toString, CH_NOID);
}
- Supplier< A> supplier()
其函数为StringBuilder::new,即通过该方法创建一个StringBuilder方法,作为累积器的初始值。
- BiConsumer<A, T> accumulator
累积器:StringBuilder::append,即会对流中的元素执行追加。
- BinaryOperator< A> combiner
组合器,也是调用append方法,进行字符串的规约。
- Function<A,R> finisher
转换器:由于累积器返回的最终对象为StringBuilder,并不是目标String类型,故需要调用StringBuilder#toString方法进行转换
- Set< Characteristics> characteristics
无任何行为。
从上面的函数定义我们可以得出该方法的作用:针对字符串流,会对流中的元素执行字符的追加动作,流元素之间没有分隔符号,示例如下:
2.2 joining(CharSequence delimiter)
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {
return joining(delimiter, “”, “”);
}
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix) {
return new CollectorImpl<>(
() -> new StringJoiner(delimiter, prefix, suffix),
StringJoiner::add, StringJoiner::merge,
StringJoiner::toString, CH_NOID);
}
- Supplier< A> supplier()
其函数为() -> new StringJoiner(delimiter, prefix, suffix),累积器的初始值为StringJoiner。
- BiConsumer<A, T> accumulator
累积器:StringJoiner::append,即会对流中的元素执行追加。
- BinaryOperator< A> combiner
组合器,StringJoiner::merge。
- Function<A,R> finisher
转换器:由于累积器返回的最终对象为StringBuilder,并不是目标String类型,故需要调用StringBuilder#toString方法进行转换
- Set< Characteristics> characteristics
无任何行为。
其示例如下:
聚合相关收集器,主要包括minBy、maxBy、sum、avg等相关函数,其主要方法声明如下:
public static Collector<T, ?, Optional> minBy(Comparator<? super T> comparator)
public static Collector<T, ?, Optional> maxBy(Comparator<? super T> comparator)
public static Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper)
public static Collector<T, ?, Long> summingLong(ToLongFunction<? super T> mapper)
public static Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper)
public static Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper)
public static Collector<T, ?, Double> averagingLong(ToLongFunction<? super T> mapper)
public static Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper)
上面这些方法比较简单,下面举个简单的例子介绍其使用:
Collectors提供了3个groupingBy重载方法,我们一个一个来理解。
4.1 从示例入手
我们从其中一个最简单的函数说起,从而慢慢引出
public static <T, K> Collector<T, ?, Map<K, List>> groupingBy(
Function<? super T, ? extends K> classifier)
- Collector<T, ?, Map<K, List< T>>>
首先我们先来关注该方法的返回值Collector<T, ?, Map<K,List< T>>,其最终返回的数据类型为:Map<K, List< T>>
- Function<? super T, ? extends K> classifier
分类函数。
示例如下:例如如下是购物车实体类,并且初始化数据如下:
public class ShopCar {
private int id;
private int sellerId;
private String sellerName;
private String goodsName;
private int buyerId;
private String buyerName;
private int num;
}
// 初始化数据如下:
public static List initShopCar() {
return Arrays.asList(
new ShopCar(1, 1, “天猫” , “华为手机”, 1 , “dingw”, 5),
new ShopCar(1, 2, “京东” , “华为手机”, 2 , “ly”, 2),
new ShopCar(1, 1, “京东” , “小米手机”, 3 , “zhl”, 3),
new ShopCar(1, 2, “1号店” , “华为手机”, 1 , “dingw”, 5),
new ShopCar(1, 2, “天猫” , “苹果手机”, 1 , “dingw”, 2)
);
}
首先我们看一下java8之前的写法:
public static void test_group_jdk7(List shopCars) {
Map<String, List> shopBySellerNameMap = new HashMap<>();
for(ShopCar c : shopCars ) {
if(shopBySellerNameMap.containsKey( c.getSellerName() )) {
shopBySellerNameMap.get(c.getSellerName()).add©;
} else {
List aList = new ArrayList<>();
shopBySellerNameMap.put(c.getSellerName(), aList);
aList.add©;
}
}
print(shopBySellerNameMap);
}
上面的代码应该很容易理解,根据商家名称进行分组,拥有相同商家的名称的购物车项组成一个集合,最终返回Map<String, List< ShopCar >>类型的数据。
那如何使用java8的流分组特性来编写对应的代码呢?下面的思考过程非常关键,经过前面的学习,我想大家应该也具备了如下分析与编写的能力?
首先其声明如下:public static <T, K> Collector<T, ?, Map<K, List< T>>> groupingBy(Function<? super T, ? extends K> classifier),那在本例中,T,K这两个参数代表什么意思呢?
T : ShopCar
K : String (sellerName的类型)
其判断的主要依据为groupingBy方法返回的参数Collector<T, ?, Map<K, List< T>>>,代表<T, A, R>,其中最后一个泛型参数R对应的就是本例需要返回的Map<K, List< T>>,故分析出T,K代表的含义。
然后再看其参数:Function<? super T, ? extends K> classifier,即接受的函数式编程接口为T -> K,即通过ShopCar 返回一个String,又根据其名称可知,该函数为一个分类函数,故基本可以写成如下代码:
public static void test_group_jdk8(List shopCars) {
Map<String, List> shopBySellerNameMap =
shopCars
.stream()
.collect(Collectors.groupingBy(ShopCar::getSellerName));
//.collect(Collectors.groupingBy( (ShopCar c) -> c.getSellerName() ))
print(shopBySellerNameMap);
}
其运行效果如下:
为了加深对groupingBy方法的理解,接下来我们重点分析一下其源码的实现。
4.2 源码分析groupingBy方法
public static <T, K> Collector<T, ?, Map<K, List>> groupingBy(Function<? super T, ? extends K> classifier) { // @1
return groupingBy(classifier, toList()); // @2
}
代码@1:分类参数,已经在上文中详细介绍。
代码@2:调用groupingBy重载方法,传入的参数为toList(),有点意思,传入的参数为Collectors.toList(),结合上文中的示例,需要返回值类型为:Map<String, List< ShopCar>>,与这里的List对应起来了。
public static <T, K, A, D> Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream) {
return groupingBy(classifier, HashMap::new, downstream);
}
该重载方法,再次调用3个参数的groupingBy方法,其中第二个参数为HashMap::new,即创建一个Map对象,我们重点关注3个参数的groupingBy。
public static <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(
Function<? super T, ? extends K> classifier,
Supplier mapFactory,
Collector<? super T, A, D> downstream) { // @1
Supplier downstreamSupplier = downstream.supplier(); // @2 start
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
K key = Objects.requireNonNull(classifier.apply(t), “element cannot be mapped to a null key”);
A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
downstreamAccumulator.accept(container, t);
}; // @2 end
BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner()); // @3
@SuppressWarnings(“unchecked”)
Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFa
【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
ctory;
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { // @4
return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
}
else { // @5
@SuppressWarnings(“unchecked”)
Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
Function<Map<K, A>, M> finisher = intermediate -> {
intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
@SuppressWarnings(“unchecked”)
M castResult = (M) intermediate;
return castResult;
};
return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
}
}
代码@1:参数介绍: