All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.magictools.core.stream.CollectorUtil Maven / Gradle / Ivy

Go to download

magic-tools 是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

The newest version!
package com.magictools.core.stream;

import com.magictools.core.lang.Opt;
import com.magictools.core.util.StrUtil;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * 可变的汇聚操作{@link Collector} 相关工具封装
 *
 * @author looly, VampireAchao
 * @since 5.6.7
 */
public class CollectorUtil {

	/**
	 * 说明已包含IDENTITY_FINISH特征 为 Characteristics.IDENTITY_FINISH 的缩写
	 */
	public static final Set CH_ID
			= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
	/**
	 * 说明不包含IDENTITY_FINISH特征
	 */
	public static final Set CH_NOID = Collections.emptySet();

	/**
	 * 提供任意对象的Join操作的{@link Collector}实现,对象默认调用toString方法
	 *
	 * @param delimiter 分隔符
	 * @param        对象类型
	 * @return {@link Collector}
	 */
	public static  Collector joining(CharSequence delimiter) {
		return joining(delimiter, Object::toString);
	}

	/**
	 * 提供任意对象的Join操作的{@link Collector}实现
	 *
	 * @param delimiter    分隔符
	 * @param toStringFunc 自定义指定对象转换为字符串的方法
	 * @param           对象类型
	 * @return {@link Collector}
	 */
	public static  Collector joining(CharSequence delimiter,
													  Function toStringFunc) {
		return joining(delimiter, StrUtil.EMPTY, StrUtil.EMPTY, toStringFunc);
	}

	/**
	 * 提供任意对象的Join操作的{@link Collector}实现
	 *
	 * @param delimiter    分隔符
	 * @param prefix       前缀
	 * @param suffix       后缀
	 * @param toStringFunc 自定义指定对象转换为字符串的方法
	 * @param           对象类型
	 * @return {@link Collector}
	 */
	public static  Collector joining(CharSequence delimiter,
													  CharSequence prefix,
													  CharSequence suffix,
													  Function toStringFunc) {
		return new SimpleCollector<>(
				() -> new StringJoiner(delimiter, prefix, suffix),
				(joiner, ele) -> joiner.add(toStringFunc.apply(ele)),
				StringJoiner::merge,
				StringJoiner::toString,
				Collections.emptySet()
		);
	}


	/**
	 * 提供对null值友好的groupingBy操作的{@link Collector}实现,可指定map类型
	 *
	 * @param classifier 分组依据
	 * @param mapFactory 提供的map
	 * @param downstream 下游操作
	 * @param         实体类型
	 * @param         实体中的分组依据对应类型,也是Map中key的类型
	 * @param         下游操作对应返回类型,也是Map中value的类型
	 * @param         下游操作在进行中间操作时对应类型
	 * @param         最后返回结果Map类型
	 * @return {@link Collector}
	 */
	public static > Collector groupingBy(Function classifier,
																				  Supplier mapFactory,
																				  Collector downstream) {
		Supplier downstreamSupplier = downstream.supplier();
		BiConsumer downstreamAccumulator = downstream.accumulator();
		BiConsumer, T> accumulator = (m, t) -> {
			K key = Opt.ofNullable(t).map(classifier).orElse(null);
			A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
			downstreamAccumulator.accept(container, t);
		};
		BinaryOperator> merger = mapMerger(downstream.combiner());
		@SuppressWarnings("unchecked")
		Supplier> mangledFactory = (Supplier>) mapFactory;

		if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
			return new SimpleCollector<>(mangledFactory, accumulator, merger, CH_ID);
		} else {
			@SuppressWarnings("unchecked")
			Function downstreamFinisher = (Function) downstream.finisher();
			Function, M> finisher = intermediate -> {
				intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
				@SuppressWarnings("unchecked")
				M castResult = (M) intermediate;
				return castResult;
			};
			return new SimpleCollector<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
		}
	}

	/**
	 * 提供对null值友好的groupingBy操作的{@link Collector}实现
	 *
	 * @param classifier 分组依据
	 * @param downstream 下游操作
	 * @param         实体类型
	 * @param         实体中的分组依据对应类型,也是Map中key的类型
	 * @param         下游操作对应返回类型,也是Map中value的类型
	 * @param         下游操作在进行中间操作时对应类型
	 * @return {@link Collector}
	 */
	public static 
	Collector> groupingBy(Function classifier,
										  Collector downstream) {
		return groupingBy(classifier, HashMap::new, downstream);
	}

	/**
	 * 提供对null值友好的groupingBy操作的{@link Collector}实现
	 *
	 * @param classifier 分组依据
	 * @param         实体类型
	 * @param         实体中的分组依据对应类型,也是Map中key的类型
	 * @return {@link Collector}
	 */
	public static  Collector>>
	groupingBy(Function classifier) {
		return groupingBy(classifier, Collectors.toList());
	}

	/**
	 * 对null友好的 toMap 操作的 {@link Collector}实现,默认使用HashMap
	 *
	 * @param keyMapper     指定map中的key
	 * @param valueMapper   指定map中的value
	 * @param mergeFunction 合并前对value进行的操作
	 * @param            实体类型
	 * @param            map中key的类型
	 * @param            map中value的类型
	 * @return 对null友好的 toMap 操作的 {@link Collector}实现
	 */
	public static 
	Collector> toMap(Function keyMapper,
									 Function valueMapper,
									 BinaryOperator mergeFunction) {
		return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
	}

	/**
	 * 对null友好的 toMap 操作的 {@link Collector}实现
	 *
	 * @param keyMapper     指定map中的key
	 * @param valueMapper   指定map中的value
	 * @param mergeFunction 合并前对value进行的操作
	 * @param mapSupplier   最终需要的map类型
	 * @param            实体类型
	 * @param            map中key的类型
	 * @param            map中value的类型
	 * @param            map的类型
	 * @return 对null友好的 toMap 操作的 {@link Collector}实现
	 */
	public static >
	Collector toMap(Function keyMapper,
							 Function valueMapper,
							 BinaryOperator mergeFunction,
							 Supplier mapSupplier) {
		BiConsumer accumulator
				= (map, element) -> map.put(Opt.ofNullable(element).map(keyMapper).get(), Opt.ofNullable(element).map(valueMapper).get());
		return new SimpleCollector<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
	}

	/**
	 * 用户合并map的BinaryOperator,传入合并前需要对value进行的操作
	 *
	 * @param mergeFunction 合并前需要对value进行的操作
	 * @param            key的类型
	 * @param            value的类型
	 * @param            map
	 * @return 用户合并map的BinaryOperator
	 */
	public static > BinaryOperator mapMerger(BinaryOperator mergeFunction) {
		return (m1, m2) -> {
			for (Map.Entry e : m2.entrySet()) {
				m1.merge(e.getKey(), e.getValue(), mergeFunction);
			}
			return m1;
		};
	}


}