java - 如何封装 Java Streams 操作
问题描述
我在使用 Java Stream
API 时看到的缺点之一是,与迭代版本相比,代码的可读性似乎较差。
顺便说一句,这就是我的想法,但我只是提供一些背景信息(以避免XY 问题),我要问的问题与此无关,所以希望这不会被视为基于意见的问题。
封装通常会增加代码的可读性(同样,只是给定上下文),所以我正在寻找封装 JavaStream
操作的最佳方法。
Stream
例如,这是以典型方式(无封装)实现的一系列简单操作:
void method1() {
List<Integer> result = IntStream.range(1, 10)
// Two Stream "intermediate" operations:
.filter(i -> i % 2 != 0).map(i -> i * 2)
.boxed().collect(Collectors.toList());
log.debug("Result: {}", result);
// Result: [2, 6, 10, 14, 18]
}
这是我通过添加方法实现封装的第一个简单尝试filterOutEvenNumbersAndMultiplyByTwo
:
IntStream filterOutEvenNumbersAndMultiplyByTwo(IntStream stream) {
return stream.filter(i -> i % 2 != 0).map(i -> i * 2);
}
void method2() {
List<Integer> result = filterOutEvenNumbersAndMultiplyByTwo(IntStream.range(1, 10))
.boxed().collect(Collectors.toList());
log.debug("Result: {}", result);
// Result: [2, 6, 10, 14, 18]
}
如您所见,我Stream
在一个新方法中封装了两个中间操作,这在这种情况下似乎没有多大意义,但这只是一个示例,可能有两个以上Stream
的操作,也可能有更复杂的操作。
新方法增加了可读性(恕我直言)并且可以进行单元测试(这是事实)。
上面的代码有效,但它看起来不是很好或干净,理想情况下,我希望能够编写如下内容:
List<Integer> result = IntStream.range(1, 10)
// This obviously does not compile
.filterOutEvenNumbersAndMultiplyByTwo()
.boxed().collect(Collectors.toList());
我想它可以完成,但需要付出很大的努力,因为我必须实现Stream
接口......
还有其他方法吗?
也许存在一个我可以使用的库?
也许我的 OO 思想正试图强制封装一些不应该的东西,但我仍然想知道这是否可能。
解决方案
filterOutEvenNumbers
只是一个谓词。
multiplyByTwo
是地图操作。
// we can unit test these
IntPredicate filterOutEvenNumbers = i -> i % 2 != 0
IntUnaryOperator multiplyByTwo = i -> i * 2;
您可以有 N 个谓词/映射操作。我们也可以在这里切换各种谓词/映射操作。
IntStream.range(1, 10)
.filter(filterOutEvenNumbers)
.map(multiplyByTwo)
.boxed()
.collect(Collectors.toList());
推荐阅读
- javascript - 手风琴遇到 jQuery 问题
- javascript - 在Javascript中按月分组日期
- python - 无法动态地将小部件添加到 QScrollArea 对象
- python - 使用 OpenCV 检测正方形/矩形
- c - 没有递归的序列 ( Sn ) 的函数
- php - 如何使用 PHP 从数组中提取多个 JSON 对象?第2部分
- unit-testing - 单元测试在执行期间冻结
- java - Java GC:Java GC 如何清除 WeakReference 对象?
- android - android studio中的任何视图都会根据设备默认主题更改背景颜色
- javascript - 在 Chrome DevTools 中同时查看 Elements 和 Sources