前公司的技术总监写了工具类,对Java Stream 进行二次封装,使用起来非常爽,全公司都在用。
我自己照着写了一遍,改了名字,分享给大家。
一共整理了10个工具方法,可以满足 Collection、List、Set、Map 之间各种类型转化。例如
- 将
Collection<OrderItem>转化为List<OrderItem> - 将
Collection<OrderItem>转化为Set<OrderItem> - 将
List<OrderItem>转化为List<Long> - 将
Set<OrderItem>转化为Set<Long> - 将
Collection<OrderItem>转化为List<Long> - 将
Collection<OrderItem>转化为Set<Long> - 从
Collection<OrderItem>中提取 Key, Map 的 Value 就是类型 OrderItem - 从
Collection<OrderItem>中提取 Key, Map 的 Value 根据 OrderItem 类型进行转化。 - 将
Map<Long, OrderItem>中的value 转化为Map<Long, Double> - value 转化时,lamada表达式可以使用
(v)->{}, 也可以使用(k,v)->{ }。
看 Collection 集合类型到 Map类型的转化。
Collection 转化为 Map
由于 List 和 Set 是 Collection 类型的子类,所以只需要实现Collection 类型转化为 Map 类型即可。
Collection转化为 Map 共分两个方法
- 从
Collection<OrderItem>到Map<Key, OrderItem>,提取 Key, Map 的 Value 就是类型 OrderItem - 从
Collection<OrderItem>到Map<Key,Value>,提取 Key, Map 的 Value 根据 OrderItem 类型进行转化。
使用样例
代码示例中把Set<OrderItem> 转化为 Map<Long, OrderItem> 和 Map<Long ,Double>。
@Test
public void testToMap() {
Collection<OrderItem> collection = coll;
Set<OrderItem> set = toSet(collection);
Map<Long, OrderItem> map = toMap(set, OrderItem::getOrderId);
}
@Test
public void testToMapV2() {
Collection<OrderItem> collection = coll;
Set<OrderItem> set = toSet(collection);
Map<Long, Double> map = toMap(set, OrderItem::getOrderId, OrderItem::getActPrice);
}
代码展示
public static <T, K> Map<K, T> toMap(Collection<T> collection, Function<? super T, ? extends K> keyMapper) {
return toMap(collection, keyMapper, Function.identity());
}
public static <T, K, V> Map<K, V> toMap(Collection<T> collection,
Function<? super T, ? extends K> keyFunction,
Function<? super T, ? extends V> valueFunction) {
return toMap(collection, keyFunction, valueFunction, pickSecond());
}
public static <T, K, V> Map<K, V> toMap(Collection<T> collection,
Function<? super T, ? extends K> keyFunction,
Function<? super T, ? extends V> valueFunction,
BinaryOperator<V> mergeFunction) {
if (CollectionUtils.isEmpty(collection)) {
return new HashMap<>(0);
}
return collection.stream().collect(Collectors.toMap(keyFunction, valueFunction, mergeFunction));
}
public static <T> BinaryOperator<T> pickFirst() {
return (k1, k2) -> k1;
}
public static <T> BinaryOperator<T> pickSecond() {
return (k1, k2) -> k2;
}
Map格式转换
转换 Map 的 Value
- 将 Map<Long, OrderItem> 中的value 转化为 Map<Long, Double>
- value 转化时,lamada表达式可以使用(v)->{}, 也可以使用 (k,v)->{ }。
测试样例
@Test
public void testConvertValue() {
Collection<OrderItem> collection = coll;
Set<OrderItem> set = toSet(collection);
Map<Long, OrderItem> map = toMap(set, OrderItem::getOrderId);
Map<Long, Double> orderId2Price = convertMapValue(map, item -> item.getActPrice());
Map<Long, String> orderId2Token = convertMapValue(map, (id, item) -> id + item.getName());
}
代码展示
public static <K, V, C> Map<K, C> convertMapValue(Map<K, V> map,
BiFunction<K, V, C> valueFunction,
BinaryOperator<C> mergeFunction) {
if (isEmpty(map)) {
return new HashMap<>();
}
return map.entrySet().stream().collect(Collectors.toMap(
e -> e.getKey(),
e -> valueFunction.apply(e.getKey(), e.getValue()),
mergeFunction
));
}
public static <K, V, C> Map<K, C> convertMapValue(Map<K, V> originMap, BiFunction<K, V, C> valueConverter) {
return convertMapValue(originMap, valueConverter, Lambdas.pickSecond());
}
public static <T> BinaryOperator<T> pickFirst() {
return (k1, k2) -> k1;
}
public static <T> BinaryOperator<T> pickSecond() {
return (k1, k2) -> k2;
}
集合类型转化
Collection 和 List、Set 的转化
- 将
Collection<OrderItem>转化为List<OrderItem> - 将
Collection<OrderItem>转化为Set<OrderItem>
public static <T> List<T> toList(Collection<T> collection) {
if (collection == null) {
return new ArrayList<>();
}
if (collection instanceof List) {
return (List<T>) collection;
}
return collection.stream().collect(Collectors.toList());
}
public static <T> Set<T> toSet(Collection<T> collection) {
if (collection == null) {
return new HashSet<>();
}
if (collection instanceof Set) {
return (Set<T>) collection;
}
return collection.stream().collect(Collectors.toSet());
}
测试样例
@Test//将集合 Collection 转化为 List
public void testToList() {
Collection<OrderItem> collection = coll;
List<OrderItem> list = toList(coll);
}
@Test//将集合 Collection 转化为 Set
public void testToSet() {
Collection<OrderItem> collection = coll;
Set<OrderItem> set = toSet(collection);
}
List和 Set 是 Collection 集合类型的子类,所以无需再转化。
List、Set 类型之间的转换
业务中有时候需要将 List<A> 转化为 List<B>。如何实现工具类呢?
public static <T, R> List<R> map(List<T> collection, Function<T, R> mapper) {
return collection.stream().map(mapper).collect(Collectors.toList());
}
public static <T, R> Set<R> map(Set<T> collection, Function<T, R> mapper) {
return collection.stream().map(mapper).collect(Collectors.toSet());
}
public static <T, R> List<R> mapToList(Collection<T> collection, Function<T, R> mapper) {
return collection.stream().map(mapper).collect(Collectors.toList());
}
public static <T, R> Set<R> mapToSet(Collection<T> collection, Function<T, R> mapper) {
return collection.stream().map(mapper).collect(Collectors.toSet());
}
测试样例
- 将
List<OrderItem>转化为List<Long> - 将
Set<OrderItem>转化为Set<Long> - 将
Collection<OrderItem>转化为List<Long> - 将
Collection<OrderItem>转化为Set<Long>
@Test
public void testMapToList() {
Collection<OrderItem> collection = coll;
List<OrderItem> list = toList(coll);
List<Long> orderIdList = map(list, (item) -> item.getOrderId());
}
@Test
public void testMapToSet() {
Collection<OrderItem> collection = coll;
Set<OrderItem> set = toSet(coll);
Set<Long> orderIdSet = map(set, (item) -> item.getOrderId());
}
@Test
public void testMapToList2() {
Collection<OrderItem> collection = coll;
List<Long> orderIdList = mapToList(collection, (item) -> item.getOrderId());
}
@Test
public void testMapToSetV2() {
Collection<OrderItem> collection = coll;
Set<Long> orderIdSet = mapToSet(collection, (item) -> item.getOrderId());
}
总结一下 以上样例包含了如下的映射场景
- 将
Collection<OrderItem>转化为List<OrderItem> - 将
Collection<OrderItem>转化为Set<OrderItem> - 将
List<OrderItem>转化为List<Long> - 将
Set<OrderItem>转化为Set<Long> - 将
Collection<OrderItem>转化为List<Long> - 将
Collection<OrderItem>转化为Set<Long> - 从
Collection<OrderItem>中提取 Key, Map 的 Value 就是类型 OrderItem - 从
Collection<OrderItem>中提取 Key, Map 的 Value 根据 OrderItem 类型进行转化。 - 将
Map<Long, OrderItem>中的value 转化为Map<Long, Double> - value 转化时,lamada表达式可以使用
(v)->{}, 也可以使用(k,v)->{ }。
我的开源项目
最后夹带一点私货,五阳最近花了3个月的时间完成一个开源项目。
开源3周以来,已有近 230 多个关注和Fork
Gitee:gitee.com/juejinwuyan…
GitHub github.com/juejin-wuya…
开源平台上有很多在线商城系统,功能很全,很完善,关注者众多,然而实际业务场景非常复杂和多样化,开源的在线商城系统很难完全匹配实际业务,广泛的痛点是
- 功能堆砌,大部分功能用不上,需要大量裁剪;
- 逻辑差异点较多,需要大量修改;
- 功能之间耦合,难以独立替换某个功能。
由于技术中间件功能诉求较为一致,使用者无需过多定制化,技术中间件开源项目以上的痛点不明显,然而电商交易等业务系统虽然通用性较多,但各行业各产品的业务差异化极大,所以导致以上痛点比较明显
所以我在思考,有没有一个开源系统,能提供电商交易的基础能力,能让开发者搭积木的方式,快速搭建一个完全契合自己业务的新系统呢?
- 他们可以通过编排和配置选择自己需要的功能,而无需在一个现成的开源系统上进行裁剪
- 他们可以轻松的新增扩展业务的差异化逻辑,不需要阅读然后修改原有的系统代码!
- 他们可以轻松的替换掉他们认为垃圾的、多余的系统组件,而不需要考虑其他功能是否会收到影响
开发者们,可以择需选择需要的能力组件,组件中差异化的部分有插件扩展点能轻松扩展。或者能支持开发者快速的重新写一个完全适合自己的新组件然后编排注册到系统中?
memberclub 就是基于这样的想法而设计的。 它的定位是电商类交易系统工具箱, 以SDK方式对外提供通用的交易能力,能让开发者像搭积木方式,从0到1,快速构建一个新的电商交易系统!
具体介绍可参见
Gitee开源地址:gitee.com/juejinwuyan…
GitHub开源地址 : github.com/juejin-wuya…
在这个项目中你可以学习到 SpringBoot 集成 以下框架或组件。
- Mybatis、Mybatis-plus 集成多数据源
- Sharding-jdbc 多数据源分库分表
- redis/redisson 缓存
- Apollo 分布式配置中心
- Spring Cloud 微服务全家桶
- RabbitMq 消息队列
- H2 内存数据库
- Swagger + Lombok + MapStruct
同时你也可以学习到以下组件的实现原理
- 流程引擎的实现原理
- 扩展点引擎实现原理
- 分布式重试组件实现原理
- 通用日志组件实现原理 参考:juejin.cn/post/740727…
- 商品库存实现原理: 参考:juejin.cn/post/731377…
- 分布式锁组件: 参考:
- Redis Lua的使用
- Spring 上下文工具类 参考: juejin.cn/post/746927…