如何在Java 8中比较两个Streams

时间:2016-01-15 19:36:24

标签: java junit java-8

比较Java 8中的两个Stream实例并找出它们是否具有相同的元素,特别是出于单元测试的目的,有什么好方法?

我现在得到的是:

@Test
void testSomething() {
  Stream<Integer> expected;
  Stream<Integer> thingUnderTest;
  // (...)
  Assert.assertArrayEquals(expected.toArray(), thingUnderTest.toArray());
}

或者:

Assert.assertEquals(
    expected.collect(Collectors.toList()),
    thingUnderTest.collect(Collectors.toList()));

但这意味着我正在构建两个集合并丢弃它们。考虑到测试流的大小,这不是性能问题,但我想知道是否有一种规范的方法来比较两个流。

8 个答案:

答案 0 :(得分:24)

static void assertStreamEquals(Stream<?> s1, Stream<?> s2)
{
    Iterator<?> iter1 = s1.iterator(), iter2 = s2.iterator();
    while(iter1.hasNext() && iter2.hasNext())
        assertEquals(iter1.next(), iter2.next());
    assert !iter1.hasNext() && !iter2.hasNext();
}

答案 1 :(得分:4)

收集测试中的流(如您所示)是执行测试的简单而有效的方法。您可以使用最简单的方式创建预期结果列表,这可能不会收集流。

或者,对于大多数用于创建模拟协作者的库,可以模拟Consumer&#34;期望&#34;一系列具有特定元素的accept()调用。 Consume StreamSELECT,然后&#34;验证&#34;它的配置期望得到了满足。

答案 2 :(得分:1)

public static boolean equalStreams(Stream<?>...streams) {
    List<Iterator<?>>is = Arrays.stream(streams).map(Stream::iterator).collect(Collectors.toList());
    while(is.stream().allMatch(Iterator::hasNext))
        if(is.stream().map(Iterator::next).distinct().limit(2).count()>1) return false;
    return is.stream().noneMatch(Iterator::hasNext);
}

答案 3 :(得分:1)

您可以断言流的内容,而无需创建Stream<> expected

assertj为此提供了流利且可读的解决方案。

import static org.assertj.core.api.Assertions.assertThat;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;

class MyTests {
    @Test
    void test() {
        Stream<Integer> actual = Stream.of(0, 8, 15); // your thingUnderTest

        assertThat(actual).containsExactly(0, 8, 15);
    }
}

答案 4 :(得分:1)

做同样事情的另一种方式:

static void assertStreamEquals(Stream<?> s1, Stream<?> s2) {
    Iterator<?> it2 = s2.iterator();
    assert s1.allMatch(o -> it2.hasNext() && Objects.equals(o, it2.next())) && !it2.hasNext();
}

答案 5 :(得分:0)

使用Guava库中的elementsEqual方法:

Iterators.elementsEqual(s1.iterator(), s2.iterator())

答案 6 :(得分:0)

如何在Java 8及更高版本中比较两个流:以比较IntStream为例

package com.techsqually.java.language.generics.basics;

import java.util.Iterator;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class TwoStreamComparision {

    public static void main(String[] args) {

        String a = "Arpan";
        String b = "Arpen";

        IntStream s1 =  a.chars();
        IntStream s2  = b.chars();

        Iterator<Integer> s1It = s1.iterator();
        Iterator<Integer> s2It = s2.iterator();

        //Code to check how many characters are not equal in both the string at their Respective Position
        int count = 0;
        while (s2It.hasNext()){
            if (!s1It.next().equals(s2It.next())){
                count++;
            }
        }
        System.out.println(count);
    }
}

答案 7 :(得分:0)

如果元素的顺序无关紧要,则可以使用流 groupingBy() 对任意数量的流进行比较,然后检查每个元素的计数。

示例是 IntStream,但您可以了解此方法背后的想法:

    IntStream stream1 = IntStream.range(1, 9);
    IntStream stream2 = IntStream.range(1, 10);

    boolean equal = IntStream.concat(stream1, stream2)
            .boxed()
            .collect(Collectors.groupingBy(Function.identity()))
            .entrySet().stream().noneMatch(e -> e.getValue().size() != 2);