Given an interface Stream
:
interface Stream<A> {
head();
A <A> tail();
Stream}
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 -> ...
}
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 -> ...
}
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 -> ...
}
class ConstantsStreams {
static class ConstantsStream implements Stream<Integer> {
private final int value;
public ConstantsStream(int value) {
this.value = value;
}
public Integer head() {
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);
}
}
class NatsStreams {
static class ByTwosStream implements Stream<Integer> {
private final int value;
public ByTwosStream(int value) {
this.value = value;
}
public Integer head() {
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);
}
}
class CombinedStreams {
static class InterleavedStream<A> implements Stream<A> {
private final Stream<A>[] ss;
public InterleavedStream(Stream<A>... ss) {
this.ss = ss;
}
public A head() {
return ss[0].head();
}
public Stream<A> tail() {
<A>[] tailSS = new Stream[ss.length];
Streamfor (int i = 0; i < ss.length - 1; i++) {
[i] = ss[i + 1];
tailSS}
[tailSS.length - 1] = ss[0].tail();
tailSSreturn new InterleavedStream<A>(tailSS);
}
}
static <A> Stream<A> combine(Stream<A>... ss) {
return new InterleavedStream<>(ss);
}
}
class Streams {
static <A> String peek(Stream<A> s) {
return s.head() + " -> " +
.tail().head() + " -> " +
s.tail().tail().head() + " -> " +
s.tail().tail().tail().head() + " -> ...";
s}
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/posts/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 -> ...