How to Compare Two Streams in Java 8

How to Compare Two Streams in Java 8

What would be a good way to compare two Stream instances in Java 8 and find out whether they have the same elements, specifically for purposes of unit testing?

What I've got now is:

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

or alternatively:

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

But that means I'm constructing two collections and discarding them. It's not a performance issue, given the size of my test streams, but I'm wondering whether there's a canonical way to compare two streams.

4

8 Answers

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

Collecting the stream under test (as you show) is a straightforward and effective way of performing the test. You may create the list of expected results in the easiest way available, which might not be collecting a stream.

Alternatively, with most libraries for creating mock collaborators, one could mock a Consumer that "expects" a series of accept() calls with particular elements. Consume the Stream with it, and then "verify" that its configured expectations were met.

Using the elementsEqual method in the Guava library:

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

You can assert the stream's content without creating a Stream<> expected.

AssertJ has fluent and readable solutions for this.

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

If order of elements doesn't matter, then comparison can be done for any number of streams using stream groupingBy() and then checking count for each element.

Example is for IntStream but you can get the idea behind this method:

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

Another way of doing the same thing:

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

How to Compare Two Streams in java 8 and above: with the example of Comparing 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);
    }
}
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Robert Thorne
Author

Robert Thorne

Robert Thorne covers electric vehicle innovations, autonomous driving systems, global mobility trends, and automotive engineering developments.