2016-01-15 4 views
17

Что было бы хорошим способом сравнить два экземпляра Stream в Java 8 и выяснить, имеют ли они одни и те же элементы, в частности, для модульного тестирования?Как сравнить два потока в 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())); 

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

+0

Я уверен, что нет никакого способа, не принуждая потоки в коллекцию или массив, как вы сделали выше. – joecoder

+5

Задайте каждый запрос 'iterator()' и пройдите по ним в стоп-стоп. –

+6

BTW, это появляется в рамках тестирования для самих Streams. Мы указали 18 режимов обхода (есть больше, это те, которые мы тестировали) и проходим по «одному» потоку всеми способами и сравниваем, что результаты идентичны (по модулю переупорядочений, разрешенных семантикой библиотеки потоков). См., Например , http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java. –

ответ

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

Я думаю, вы можете использовать 'BaseStream s1, BaseStream s2' для поддержки' IntStream', 'LongStream' и' DoubleStream'. –

+0

@ Тагир Валеев - хорошая идея. И для одержимых производительностью, они должны перегружать 'assertStreamEquals (IntStream, IntStream)' и т. Д. – ZhongYu

4

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

В качестве альтернативы, с большинством библиотек для создания имитирующих коллабораторов можно было бы издеваться над Consumer, который «ожидает» серии вызовов accept() с определенными элементами. ConsumeStream, а затем «проверьте», что его настроенные ожидания были выполнены.

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); 
} 
Смежные вопросы