Как сравнить два потока в Java 8

Что было бы хорошим способом сравнить два экземпляра Stream в Java 8 и выяснить, имеют ли они одни и те же элементы, специально для целей модульного тестирования?

Теперь у меня есть:

@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()));

Но это означает, что я строю две коллекции и отбрасываю их. Это не проблема производительности, учитывая размер моих тестовых потоков, но мне интересно, существует ли канонический способ сравнения двух потоков.

Ответы

Ответ 1

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();
}

Ответ 2

Сбор тестируемого потока (как вы показываете) представляет собой простой и эффективный способ проведения теста. Вы можете создать список ожидаемых результатов самым простым способом, который может не собирать поток.

В качестве альтернативы, с большинством библиотек для создания макетных коллабораторов можно было издеваться над Consumer, который "ожидает" серии вызовов accept() с определенными элементами. Consume Stream с ним, а затем "проверьте", что его настроенные ожидания были выполнены.

Ответ 3

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);
}

Ответ 4

Использование метода elementsEqual в библиотеке Guava:

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

Ответ 5

Как сравнить два потока в 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);
    }
}

Ответ 6

Вы можете утверждать содержимое потока, не создавая 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);
    }
}