让数据流转换代码更加健壮流畅:List的Stream包装
2021/5/16 10:28:48
本文主要是介绍让数据流转换代码更加健壮流畅:List的Stream包装,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
为什么业务代码总是显得不够清晰 ? 因为开发人员总喜欢把业务与技术细节掺杂在一起。如下所示:
要改善这样的代码,需要将技术细节提取成可复用的基础库,而业务则可写成声明式的:
先创建一个 StreamUtil 工具类:
public class StreamUtil { public static <T,R> List<R> map(List<T> data, Function<T, R> mapFunc) { if (CollectionUtil.isEmpty(data)) { return new ArrayList(); } return data.stream().map(mapFunc).collect(Collectors.toList()); } public static <T> List<T> filter(List<T> data, Predicate<T> filterFunc) { if (CollectionUtil.isEmpty(data)) { return new ArrayList(); } return data.stream().filter(filterFunc).collect(Collectors.toList()); } public static <T,R> List<R> filterAndMap(List<T> data, Predicate<T> filterFunc, Function<T, R> mapFunc) { if (CollectionUtil.isEmpty(data)) { return new ArrayList(); } return data.stream().filter(filterFunc).map(mapFunc).collect(Collectors.toList()); } }
则原来 stream 流转换代码可写成:
rules = StreamUtil.filter(rules, rule -> BaselineUtils.matchPlatform(rule, platforms)); baseLineRules = StreamUtil.filter(rules, rule -> rule.getFamily() == BaselineRule.FAMILY_SYSTEM);
实际上, StreamUtil.filter 不如 rules.filter(testFunc) 更可读和流畅。如果能写成如下更好:
stream(rules).filter(rule -> BaselineUtils.matchPlatform(rule, platforms));
这需要对 List 做一个 Stream 的包装:
ListStream.java
/** * @Description 列表的 Stream 包装 * @Date 2021/5/16 7:51 上午 * @Created by qinshu */ public class ListStream<T> { private List<T> origin; public ListStream(List<T> list) { if (list == null) { this.origin = new ArrayList<>(); } else { this.origin = list; } } public static <T> ListStream<T> stream(List<T> list) { return new ListStream<>(list); } public <R> List<R> map(Function<? super T, R> func) { return origin.stream().map(func).collect(Collectors.toList()); } public <R> Set<R> mapToSet(Function<? super T, R> func) { return origin.stream().map(func).collect(Collectors.toSet()); } public List<T> filter(Predicate<? super T> predicate) { return origin.stream().filter(predicate).collect(Collectors.toList()); } public <R> List<R> filterAndMapChain(List<Predicate<? super T>> beforeFilters, Function<? super T,R> mapFunc, Predicate<R>... afterFilters) { Stream<T> stream = origin.stream(); Stream<R> midResult = null; if (beforeFilters != null) { for (Predicate f: beforeFilters) { stream = stream.filter(f); } } if (mapFunc != null) { midResult = stream.map(mapFunc); } if (afterFilters != null) { for (Predicate<R> f: afterFilters) { midResult = midResult.filter(f); } } return midResult.collect(Collectors.toList()); } }
单测:
public class ListStreamTest { @Test public void testNull() { List<Integer> ints = stream(null).map(x -> (int)x + 1); Assert.assertEquals(ints.size(), 0); } @Test public void testMap() { List<Integer> ints = stream(Arrays.asList(1,2,3,4,5)).map(x -> x*2); Assert.assertArrayEquals(ints.toArray(new Integer[0]), new Integer[]{2,4,6,8,10}); } @Test public void testFilter() { List<Integer> ints = stream(Arrays.asList(1,2,3,4,5)).filter(x -> x%2 ==0); Assert.assertArrayEquals(ints.toArray(new Integer[0]), new Integer[]{2,4}); } @Test public void testFilterAndMapChain() { List<Integer> ints = stream(Arrays.asList(1,2,3,4,5)).filterAndMapChain( Arrays.asList(x -> x%2==1), x -> x*2, x -> x > 8); Assert.assertArrayEquals(ints.toArray(new Integer[0]), new Integer[]{10}); } }
这样,数据流转换代码就更加健壮和流畅。
很多人或许会觉得:把代码写得那么好图啥?其实,我是把代码表达当成一种思维的训练。 好代码不仅仅关乎习惯和态度,也关乎对设计和技术的理解。
这篇关于让数据流转换代码更加健壮流畅:List的Stream包装的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南