如何封装Java Streams操作[关闭]

问题描述 投票:6回答:1

使用JavaStreamAPI时看到的缺点之一是,与迭代版本相比,该代码似乎可读性较差。

顺便说一句,这就是我的想法,但是我只是给出一些上下文(以避免the XY problem),我要问的是与此无关的,因此希望这将not被认为是基于意见问题。

封装通常可以提高代码的可读性(再次,仅给出给定的上下文),因此我正在寻找封装Java Stream操作的最佳方法。

例如,这是简单的一系列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操作,并且更复杂的。

新方法提高了可读性(IMHO),并且可以进行单元测试(这是事实)。上面的代码可以工作,但是看起来不是很漂亮或干净,理想情况下,我希望能够写一些东西:]

        List<Integer> result = IntStream.range(1, 10)

                // This obviously does not compile
                .filterOutEvenNumbersAndMultiplyByTwo()

                .boxed().collect(Collectors.toList());

我想可以做到,但需要大量的精力,因为我必须实现Stream接口...

还有另一种方法吗?也许我可以使用一个图书馆?也许我的面向对象的思想正在试图对并非本意的东西进行封装,但我仍然想知道是否有可能。

java java-stream
1个回答
2
投票

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());
© www.soinside.com 2019 - 2024. All rights reserved.