filter - Java Streams - Filtering on previously filtered values -
i experimenting java's streams , trying figure out possible strengths , weaknesses. trying implement sieve of eratosthenes using stream, cannot seem find way loop through filtered values without storing them in separate collection.
i wanting accomplish this:
intstream mystream = intstream.range(0,3); mystream.filter(s -> { system.out.print("[filtering "+s+"] "); mystream.foreach(q -> system.out.print(q+", ")); system.out.println(); return true; //eventually respond values observed on line above });
with desired output of:
[filtering 0] [filtering 1] 0, [filtering 2] 0, 1, [filtering 3] 0, 1, 2,
note while filtering each new value filtered values observed. allow easy implementation of sieve of eratosthenes because filter out non-prime values , each new value check divisibility against numbers have passed prime filter.
however, above example gives me error in netbeans:
local variables referenced lambda expression must final or final
this appears because referencing mystream within filter acting on mystream. there way of working around error (ie. making final copy of stream containing values have been filtered far), or there better approach sort of problem without using separate collection store values?
i managed create infinite stream
of prime numbers using sieve of eratosthenes, not use past values. instead, removes multiples of prime in tail (in lazy way, because tail infinite), original sieve of eratosthenes algorithm. that, used iterator
auxiliary (because stream
can used once) , implemented lazyconcat
streams.
class streamutils { public static intstream fromiterator(primitiveiterator.ofint it) { return streamsupport.intstream( spliterators.spliteratorunknownsize(it, spliterator.ordered), false); } public static intstream lazyconcat(supplier<intstream> a, supplier<intstream> b) { return streamsupport.intstream(new spliterator.ofint() { boolean beforesplit = true; spliterator.ofint spliterator; @override public ofint trysplit() { return null; } @override public long estimatesize() { return long.max_value; } @override public int characteristics() { return spliterator.ordered; } @override public boolean tryadvance(intconsumer action) { boolean hasnext; if (spliterator == null) { spliterator = a.get().spliterator(); } hasnext = spliterator.tryadvance(action); if (!hasnext && beforesplit) { beforesplit = false; spliterator = b.get().spliterator(); hasnext = spliterator.tryadvance(action); } return hasnext; } }, false); } }
my sieve of eratosthenes stream looks this:
class primes { public static intstream stream() { return sieve(intstream.iterate(2, n -> n + 1)); } private static intstream sieve(intstream s) { primitiveiterator.ofint = s.iterator(); int head = it.nextint(); intstream tail = streamutils.fromiterator(it); return streamutils.lazyconcat( () -> intstream.of(head), () -> sieve(tail.filter(n -> n % head != 0))); } }
then can use way:
system.out.println(primes.stream().limit(20).boxed().collect(collectors.tolist()));
output:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
i think exercise, seems quite inefficient , not stack-friendly @ all.
Comments
Post a Comment