Created
August 14, 2013 03:06
-
-
Save qzchenwl/6227684 to your computer and use it in GitHub Desktop.
Stream implemented in java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package util; | |
import org.springframework.util.Assert; | |
import java.math.BigDecimal; | |
import java.util.Iterator; | |
public class Test { | |
public static void main(String[] args) { | |
Stream<Integer> evens = filter(new F1<Integer, Boolean>() { | |
@Override | |
public Boolean f(Integer a) { | |
return a % 2 == 0; | |
} | |
}, natures); | |
Stream<BigDecimal> sub = take(1000, fibs); | |
for(BigDecimal i : sub) { | |
System.out.println(i); | |
} | |
} | |
public static abstract class Stream<T> implements Iterable<T> { | |
public abstract T car(); | |
public abstract Stream<T> cdr(); | |
public static <T> Stream<T> cons(final T a, final Delay<Stream<T>> delayed) { | |
return new Stream<T>() { | |
@Override | |
public T car() { | |
return a; | |
} | |
@Override | |
public Stream<T> cdr() { | |
return delayed.memForce(); | |
} | |
@Override | |
public Iterator iterator() { | |
return new StreamIterator<T>(this); | |
} | |
}; | |
} | |
public static class StreamIterator<T> implements Iterator<T> { | |
private Stream<T> stream; | |
public StreamIterator(Stream<T> stream) { | |
this.stream = stream; | |
} | |
@Override | |
public boolean hasNext() { | |
return stream != null; | |
} | |
@Override | |
public T next() { | |
T e = stream.car(); | |
stream = stream.cdr(); | |
return e; | |
} | |
@Override | |
public void remove() { | |
throw new UnsupportedOperationException(); | |
} | |
} | |
} | |
public static abstract class Delay<T> { | |
private T result; | |
public T memForce() { | |
if (result == null) { | |
result = force(); | |
} | |
return result; | |
} | |
public abstract T force(); | |
} | |
public static Stream<Integer> ones = Stream.cons(1, new Delay<Stream<Integer>>() { | |
@Override | |
public Stream<Integer> force() { | |
return ones; | |
} | |
}); | |
public static Stream<Integer> ints_from(final int from) { | |
return Stream.cons(from, new Delay<Stream<Integer>>() { | |
@Override | |
public Stream<Integer> force() { | |
return ints_from(from + 1); | |
} | |
}); | |
} | |
public static Stream<Integer> natures = ints_from(1); | |
public static Stream<BigDecimal> fibgen(final BigDecimal a, final BigDecimal b) { | |
return Stream.cons(a, new Delay<Stream<BigDecimal>>() { | |
@Override | |
public Stream<BigDecimal> force() { | |
return fibgen(b, a.add(b)); | |
} | |
}); | |
} | |
public static Stream<BigDecimal> fibs = fibgen(BigDecimal.valueOf(0), BigDecimal.valueOf(1)); | |
public static abstract class F1<A,B> { | |
public abstract B f(A a); | |
} | |
public static <T> Stream<T> filter(final F1<T, Boolean> p, final Stream<T> s) { | |
if (s == null) return null; | |
T a = s.car(); | |
if (p.f(a)) { | |
return Stream.cons(a, new Delay<Stream<T>>() { | |
@Override | |
public Stream<T> force() { | |
return filter(p, s.cdr()); | |
} | |
}); | |
} | |
else { | |
return filter(p, s.cdr()); | |
} | |
} | |
public static <T> Stream<T> take(final int n, final Stream<T> s) { | |
Assert.isTrue(n >= 0); | |
if (n == 0) return null; | |
return Stream.cons(s.car(), new Delay<Stream<T>>() { | |
@Override | |
public Stream<T> force() { | |
return take(n-1, s.cdr()); | |
} | |
}); | |
} | |
public static <A, B> Stream<B> map(final F1<A, B> f, final Stream<A> s) { | |
return Stream.cons(f.f(s.car()), new Delay<Stream<B>>() { | |
@Override | |
public Stream<B> force() { | |
return map(f, s.cdr()); | |
} | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment