2

I am trying to learn how to use Java Streams in a situation where I would normally do imperatively.

So if I have stream 1 that looks like this:

1 4 3 5 6 9 4 1 ...

and stream 2 looks like this

1 0 3 0 0 9 4 0 ...

I would like it create a third stream that only contains the elements that are equal, so:

1 3 9 4 ...
Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
sanz
  • 1,232
  • 1
  • 9
  • 17
  • what code have you tried? – Coding Enthusiast May 15 '15 at 18:28
  • For another case, I was doing a normal filter oneStream.filter(line -> matchesOtherLines(line, lines)), I thought I could maybe filter based on two streams but can't figure out anything. – sanz May 15 '15 at 19:03
  • 1
    You could "zip" the streams together. It's not built-in, but you can use techniques from the answers to [this question](http://stackoverflow.com/questions/17640754/zipping-streams-using-jdk8-with-lambda-java-util-stream-streams-zip). – Stuart Marks May 16 '15 at 22:03

3 Answers3

3

That doesn't really look feasible with streams other than converting them to iterators and doing it by hand that way. There's not really a way to combine two streams like that.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
3

If your sources are random access lists, you can do the following:

List<Integer> list1 = Arrays.asList(1, 4, 3, 5, 6, 9, 4, 1, ...);
List<Integer> list2 = Arrays.asList(1, 0, 3, 0, 0, 9, 4, 0, ...);

IntStream.range(0, list1.size())
    .mapToObj(i -> list1.get(i).equals(list2.get(i)) ? list1.get(i) : null)
    .filter(Objects::nonNull).collect(Collectors.toList());

In my StreamEx library there's a shortcut specially for this case:

StreamEx.zip(list1, list2, (a, b) -> a.equals(b) ? a : null).nonNull().toList();

Also if you don't care about parallel processing, you can use jOOL library which allows you to zip two streams together:

Seq.of(list1).zip(Seq.of(list2), (a, b) -> a.equals(b) ? a : null)
             .filter(Objects::nonNull).toList();

This will perform badly for parallel streams, but works with any stream source (not only random access lists or arrays).

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
1

You have to zip your streams - I can recommend you protonpack tiny library. Here is a test method:

import com.codepoetics.protonpack.StreamUtils;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import org.junit.Test; 

// ... skipped test class declaration
@Test
public void shouldRetrieveOnlyEqual() {
    // given
    Stream<Integer> s1 = Stream.of(1, 4, 3, 5, 6, 9, 4, 1);
    Stream<Integer> s2 = Stream.of(1, 0, 3, 0, 0, 9, 4, 0);

    // when
    List<Integer> actual = StreamUtils.zip(s1, s2, (v1, v2) -> v1.equals(v2) ? v1 : null)
            .filter(Objects::nonNull).collect(Collectors.toList());

    // then
    assertThat(actual, contains(1, 3, 9, 4));
}
ytterrr
  • 3,036
  • 6
  • 23
  • 32