# Combining Streams in Java

July 31, 2013

Given an interface `Stream`:

``````interface Stream<A> {
Stream<A> tail();
}``````

## Constant streams

Write the functions `zeroes`, `ones`, and `twos`, which return streams of values `0`, `1`, and `2`:

``````Stream<Integer> zeroes() {
return ???; // 0 -> 0 -> 0 -> 0 -> ...
}

Stream<Integer> ones() {
return ???; // 1 -> 1 -> 1 -> 1 -> ...
}

Stream<Integer> twos() {
return ???; // 2 -> 2 -> 2 -> 2 -> ...
}``````

## Natural numbers streams

Write the functions `evens` and `odds`, which return streams of the even natural numbers (0, 2, 4, ...) and the odd natural numbers (1, 3, 5, ...):

``````Stream<Integer> evens() {
return ???; // 0 -> 2 -> 4 -> 6 -> ...
}

Stream<Integer> odds() {
return ???; // 1 -> 3 -> 5 -> 7 -> ...
}``````

## Combined streams

Write the function `combine`, which interleaves its argument streams in constant time:

``````static <A> Stream<A> combine(Stream<A>... ss) {
return ???; // combine(evens(), odds()) = 0 -> 1 -> 2 -> 3 -> ...
}``````

# Solution

Here is one possible solution.

## Constants streams

``````class ConstantsStreams {

static class ConstantsStream implements Stream<Integer> {

private final int value;

public ConstantsStream(int value) {
this.value = value;
}

return value;
}

public Stream<Integer> tail() {
return this;
}
}

static Stream<Integer> zeroes() {
return new ConstantsStream(0);
}

static Stream<Integer> ones() {
return new ConstantsStream(1);
}

static Stream<Integer> twos() {
return new ConstantsStream(2);
}
}``````

## Natural numbers streams

``````class NatsStreams {

static class ByTwosStream implements Stream<Integer> {

private final int value;

public ByTwosStream(int value) {
this.value = value;
}

return value;
}

public Stream<Integer> tail() {
return new ByTwosStream(value + 2);
}

}

static Stream<Integer> evens() {
return new ByTwosStream(0);
}

static Stream<Integer> odds() {
return new ByTwosStream(1);
}
}``````

## Combined streams

``````class CombinedStreams {

static class InterleavedStream<A> implements Stream<A> {

private final Stream<A>[] ss;

public InterleavedStream(Stream<A>... ss) {
this.ss = ss;
}

}

public Stream<A> tail() {
Stream<A>[] tailSS = new Stream[ss.length];
for (int i = 0; i < ss.length - 1; i++) {
tailSS[i] = ss[i + 1];
}
tailSS[tailSS.length - 1] = ss[0].tail();
return new InterleavedStream<A>(tailSS);
}

}

static <A> Stream<A> combine(Stream<A>... ss) {
return new InterleavedStream<>(ss);
}
}``````

## Demo

``````class Streams {

static <A> String peek(Stream<A> s) {
return s.head()                      + " -> " +
s.tail().head()               + " -> " +
s.tail().tail().head()        + " -> " +
}

public static void main(String[] args) {

System.out.println();
System.out.println("Constants streams:");
System.out.println("  zeroes() = " + peek(ConstantsStreams.zeroes()));
System.out.println("    ones() = " + peek(ConstantsStreams.ones()));
System.out.println("    twos() = " + peek(ConstantsStreams.twos()));

System.out.println();
System.out.println("Natural numbers streams:");
System.out.println("  evens() = " + peek(NatsStreams.evens()));
System.out.println("   odds() = " + peek(NatsStreams.odds()));

System.out.println();
System.out.println("Combined streams:");
System.out.println("  combine(evens(), odds()) = " +
peek(CombinedStreams.combine(NatsStreams.evens(), NatsStreams.odds()))
);
}
}``````

This file is literate Java, and can be run using Codedown:

``````\$ curl https://earldouglas.com/exercises/java-streams.md |
codedown java > Streams.java
\$ javac Streams.java
\$ java Streams

Constants streams:
zeroes() = 0 -> 0 -> 0 -> 0 -> ...
ones() = 1 -> 1 -> 1 -> 1 -> ...
twos() = 2 -> 2 -> 2 -> 2 -> ...

Natural numbers streams:
evens() = 0 -> 2 -> 4 -> 6 -> ...
odds() = 1 -> 3 -> 5 -> 7 -> ...

Combined streams:
combine(evens(), odds()) = 0 -> 1 -> 2 -> 3 -> ...``````