All Downloads are FREE. Search and download functionalities are using the official Maven repository.

groovy.stream.Stream Maven / Gradle / Ivy

Go to download

A collection of classes to give a fluent builder for Streams (Lazy Groovy Generators).

The newest version!
/*
 * Copyright 2013-2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package groovy.stream ;

import groovy.lang.Closure ;

import groovy.stream.iterators.* ;
import groovy.stream.iterators.java.* ;
import groovy.stream.iterators.groovy.* ;
import groovy.stream.functions.Function ;
import groovy.stream.functions.Function2 ;
import groovy.stream.functions.Predicate ;
import groovy.stream.functions.IndexedFunction ;
import groovy.stream.functions.IndexedFunction2 ;
import groovy.stream.functions.IndexedPredicate ;

import java.io.BufferedReader ;

import java.lang.reflect.Array ;

import java.util.ArrayList ;
import java.util.Collection ;
import java.util.Iterator ;
import java.util.List ;
import java.util.Map ;

import java.util.jar.JarEntry ;
import java.util.jar.JarFile ;

import java.util.zip.ZipEntry ;
import java.util.zip.ZipFile ;


/**
 *
 * @author Tim Yates
 * @param  the type of each element returned from the Stream.
 */
public class Stream implements Iterator {
    private final Iterator iterator ;

    private Stream( Iterator iterator ) {
        this.iterator = iterator ;
    }

    /**
     * Filter the current stream, passing each element through a predicate filter.
     *
     * 
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..3 )
     *                .filter { it % 2 == 1 }
     *                .collect() == [ 1, 3 ]
     * 
* * @param predicate A single parameter closure to pass the element through, * returning {@code true} if the element is to be included. * @return A new {@code Stream} wrapping a {@link FilteringIterator} */ public Stream filter( Closure predicate ) { return new Stream( new FilteringIterator( iterator, predicate, false ) ) ; } /** * Filter the current stream, passing each element through a predicate filter (Java friendly version). * * @param predicate A {@link Predicate} instance returning {@code true} from it's {@code call} method * if the element is to be included. * @return A new {@code Stream} wrapping a {@link FilteringIteratorForPredicate} */ public Stream filter( Predicate predicate ) { return new Stream( new FilteringIteratorForPredicate( iterator, predicate ) ) ; } /** * Filter the current stream, passing each element and it's index through a predicate filter. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..3 )
     *                .filterWithIndex { it, index -> index % 2 == 1 }
     *                .collect() == [ 2 ]
     * 
* * @param predicate A two parameter closure, the first parameter being the * element in the {@code Stream}, the second the index (starting at 0). * @return A new {@code Stream} wrapping a {@link FilteringIterator} */ public Stream filterWithIndex( Closure predicate ) { return new Stream( new FilteringIterator( iterator, predicate, true ) ) ; } /** * Filter the current stream, passing each element and its index through a predicate filter (Java friendly version). * * @param predicate An {@link IndexedPredicate} instance returning {@code true} from it's {@code call} method * if the element is to be included. * @return A new {@code Stream} wrapping a {@link FilteringIteratorForIndexedPredicate} */ public Stream filterWithIndex( IndexedPredicate predicate ) { return new Stream( new FilteringIteratorForIndexedPredicate( iterator, predicate ) ) ; } /** * Returns a new {@code Stream} which will iterate the elements in the current {@code Stream}, * followed by the elements in the {@code other} {@code Stream}. * *
     *   import groovy.stream.*
     *
     *   def a = Stream.from( 1..3 )
     *   def b = Stream.from( 'a'..'c' )
     *
     *   assert a.concat( b ).collect() == [ 1, 2, 3, 'a', 'b', 'c' ]
     * 
* * @param other The {@code Stream} to iterate after the current one is exhausted. * @return A new {@code Stream} wrapping a {@link ConcatenationIterator} */ public Stream concat( Iterator other ) { return new Stream( new ConcatenationIterator( iterator, other ) ) ; } /** * Skip {@code n} elements. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..10 )
     *                .skip( 6 ).collect() == [ 7, 8, 9, 10 ]
     * 
* * @param n the number of elements to skip * @return A new {@code Stream} wrapping a {@link SkipIterator} */ public Stream skip( int n ) { return new Stream( new SkipIterator( iterator, n ) ) ; } /** * Takes a {@code Closure} that returns a {@code Collection}. Each element * in this {@code Collection} is passed on in turn, before the next element is * fetched from upstream, and the Closure executed again. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..3 )
     *                .flatMap { [ it ] * it }
     *                .collect() == [ 1, 2, 2, 3, 3, 3 ]
     * 
* * @param The type of the new Stream. * @param map A single parameter closure to pass the element through, * returning a new Collection of elements to iterate. * @return A new {@code Stream} wrapping a {@link FlatMapIterator} */ public Stream flatMap( Closure> map ) { return new Stream( new FlatMapIterator( iterator, map, false ) ) ; } /** * Takes a {@link Function} that returns a {@code Collection}. Each element * in this {@code Collection} is passed on in turn, before the next element is * fetched from upstream, and the {@link Function} is executed again. * * @param The type of the new Stream. * @param map A single {@link Function} to pass the element through, returning a * new Collection of elements to iterate. * @return A new {@code Stream} wrapping a {@link FlatMapIteratorForFunction} */ public Stream flatMap( Function> map ) { return new Stream( new FlatMapIteratorForFunction( iterator, map ) ) ; } /** * Takes a {@code Closure} that returns a {@code Collection}. Each element * in this {@code Collection} is passed on in turn, before the next element is * fetched from upstream, and the Closure executed again. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..3 )
     *                .flatMapWithIndex { it, index -> [ it ] * index }
     *                .collect() == [ 2, 3, 3 ]
     * 
* * @param The type of the new Stream. * @param map A two parameter closure to pass the element and it's index through, * returning a new Collection of elements to iterate. * @return A new {@code Stream} wrapping a {@link FlatMapIterator} */ public Stream flatMapWithIndex( Closure> map ) { return new Stream( new FlatMapIterator( iterator, map, true ) ) ; } /** * Takes an {@link IndexedFunction} that returns a {@code Collection}. Each element * in this {@code Collection} is passed on in turn, before the next element is * fetched from upstream, and the {@link IndexedFunction} is executed again. * * @param The type of the new Stream. * @param map A single {@link IndexedFunction} to pass the element and its index through, * returning a new Collection of elements to iterate. * @return A new {@code Stream} wrapping a {@link FlatMapIteratorForIndexedFunction} */ public Stream flatMapWithIndex( IndexedFunction> map ) { return new Stream( new FlatMapIteratorForIndexedFunction( iterator, map ) ) ; } /** * Inspect every value in the {@code Stream} and pass it on unmodified. * *
     *   import groovy.stream.*
     *
     *   def list = []
     *   assert Stream.from( 1..3 )
     *                .tap { list << it }
     *                .collect() == [ 1, 2, 3 ]
     *   assert list == [ 1, 2, 3 ]
     * 
* * @param output The {@code Closure} to be called for every element * @return A new {@code Stream} wrapping a {@link TapIterator} */ public Stream tap( Closure output ) { return tapEvery( 1, output ) ; } /** * Inspect every value in the {@code Stream} and pass it on. * * @see #tap(groovy.lang.Closure) * @param output The {@code Function} to be called for every element * @return A new {@code Stream} wrapping a {@link TapIteratorForFunction} */ public Stream tap( Function output ) { return tapEvery( 1, output ) ; } /** * Inspect the every nth value in the {@code Stream} and pass it on unmodified. * *
     *   import groovy.stream.*
     *
     *   def list = []
     *   assert Stream.from( 1..3 )
     *                .tapEvery( 2 ) { list << it }
     *                .collect() == [ 1, 2, 3 ]
     *   assert list == [ 2 ]
     * 
* * @param n the elements to inspect * @param output The {@code Closure} to be called for every nth element * @return A new {@code Stream} wrapping a {@link TapIterator} */ public Stream tapEvery( int n, Closure output ) { return new Stream( new TapIterator( iterator, n, false, output ) ) ; } /** * Inspect the every nth value in the {@code Stream} and pass it on. * * @see #tapEvery(int, groovy.lang.Closure) * @param n the elements to inspect * @param output The {@code Function} to be called for every nth element * @return A new {@code Stream} wrapping a {@link TapIteratorForFunction} */ public Stream tapEvery( int n, Function output ) { return new Stream( new TapIteratorForFunction( iterator, n, output ) ) ; } /** * Inspect every value in the {@code Stream} with its {@code index} and pass it on unmodified. * *
     *   import groovy.stream.*
     *
     *   def list = []
     *   assert Stream.from( 1..3 )
     *                .tapWithIndex { it, idx -> list << [ (it):idx ] }
     *                .collect() == [ 1, 2, 3 ]
     *   assert list == [ [ 1:0 ], [ 2:1 ], [ 3:2 ] ]
     * 
* * @param output The closure to call for each element in the Stream. * @return A new {@code Stream} wrapping a {@link TapIterator} */ public Stream tapWithIndex( Closure output ) { return tapEveryWithIndex( 1, output ) ; } /** * Inspect every value in the {@code Stream} with its {@code index} and pass it on unmodified. * * @see #tapWithIndex(groovy.lang.Closure) * @param output The {@link IndexedFunction} to call for each element in the Stream. * @return A new {@code Stream} wrapping a {@link TapIteratorForIndexedFunction} */ public Stream tapWithIndex( IndexedFunction output ) { return tapEveryWithIndex( 1, output ) ; } /** * Inspect the every nth value in the {@code Stream} with its index and pass it on unmodified. * *
     *   import groovy.stream.*
     *
     *   def list = []
     *   assert Stream.from( 1..3 )
     *                .tapEveryWithIndex( 2 ) { it, index -> list << [ (it):index ] }
     *                .collect() == [ 1, 2, 3 ]
     *   assert list == [ [2:1] ]
     * 
* * @param n the elements to inspect * @param output The {@link Closure} to be called for every nth element * @return A new {@code Stream} wrapping a {@link TapIterator} */ public Stream tapEveryWithIndex( int n, Closure output ) { return new Stream( new TapIterator( iterator, n, true, output ) ) ; } /** * Inspect the every nth value in the {@code Stream} with its index and pass it on unmodified. * * @see #tapEveryWithIndex(int, groovy.lang.Closure) * @param n the elements to inspect * @param output The {@link IndexedFunction} to be called for every nth element * @return A new {@code Stream} wrapping a {@link TapIteratorForIndexedFunction} */ public Stream tapEveryWithIndex( int n, IndexedFunction output ) { return new Stream( new TapIteratorForIndexedFunction( iterator, n, output ) ) ; } /** * Maps the elements of a {@code Stream} to a new value as they are requested. Each * element is passed in to a one arg closure, and the result of the {@link Closure} * is returned as the next element in the {@code Stream}. The element is also * set as the delegate of the {@link Closure}, so you can access map entries * by name. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( x:1..3, y:'a'..'c' )
     *                .map { "$x:$y" }
     *                .collect() == [ "1:a", "1:b", "1:c",
     *                                "2:a", "2:b", "2:c",
     *                                "3:a", "3:b", "3:c" ]
     * 
* * @param The type of the new Stream. * @param map The transforming Closure. * @return A new {@code Stream} wrapping a {@link TransformingIterator} */ public Stream map( Closure map ) { return new Stream( new TransformingIterator( iterator, map, false ) ) ; } /** * Maps the elements of a {@code Stream} to a new value as they are requested. Each * element is passed in to a {@link Function}, the result of which is returned as the * next element in the {@code Stream}. * * @see #map(groovy.lang.Closure) * @param The type of the new Stream. * @param map The transforming {@link Function}. * @return A new {@code Stream} wrapping a {@link TransformingIteratorForFunction} */ public Stream map( Function map ) { return new Stream( new TransformingIteratorForFunction( iterator, map ) ) ; } /** * Maps the elements of a {@code Stream} to a new value as they are requested. Each * element plus an index is passed in to a two arg closure, and the result of * the {@link Closure} is returned as the next element in the {@code Stream}. * The element is also set as the delegate of the {@link Closure}, so you can * access map entries by name. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( x:1..3, y:'a'..'c' )
     *                .mapWithIndex { it, idx -> "${x}:${it.y}:${idx}" }
     *                .collect() == [ "1:a:0", "1:b:1", "1:c:2",
     *                                "2:a:3", "2:b:4", "2:c:5",
     *                                "3:a:6", "3:b:7", "3:c:8" ]
     * 
* * @param The type of the new Stream. * @param map The transforming Closure. * @return A new {@code Stream} wrapping a {@link TransformingIterator} */ public Stream mapWithIndex( Closure map ) { return new Stream( new TransformingIterator( iterator, map, true ) ) ; } /** * Maps the elements of a {@code Stream} to a new value as they are requested. Each * element plus an index is passed in to an {@link IndexedFunction}, and the result of * this is returned as the next element in the {@code Stream}. * * @see #mapWithIndex(groovy.lang.Closure) * @param The type of the new Stream. * @param map The transforming {@link IndexedFunction}. * @return A new {@code Stream} wrapping a {@link TransformingIteratorForIndexedFunction} */ public Stream mapWithIndex( IndexedFunction map ) { return new Stream( new TransformingIteratorForIndexedFunction( iterator, map ) ) ; } /** * When the {@link Closure} predicate returns {@code true}, the stream is stopped. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..5 )
     *                .until { it > 3 }
     *                .collect() == [ 1, 2, 3 ]
     * 
* * @param predicate The {@link Closure} that stops the Stream when it returns {@code true}. * @return A new {@code Stream} wrapping an {@link UntilIterator} */ public Stream until( Closure predicate ) { return new Stream( new UntilIterator( iterator, predicate, false ) ) ; } /** * When the {@link Predicate} returns {@code true}, the stream is stopped. * * @see #until(groovy.lang.Closure) * @param predicate The {@link Predicate} that stops the Stream when it returns {@code true}. * @return A new {@code Stream} wrapping an {@link UntilIteratorForPredicate} */ public Stream until( Predicate predicate ) { return new Stream( new UntilIteratorForPredicate( iterator, predicate ) ) ; } /** * Calls the {@link Closure} predicate with the current element and the index in the stream. * When the predicate returns {@code true}, the stream is stopped. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..5 )
     *                .untilWithIndex { it, index -> index == 2 }
     *                .collect() == [ 1, 2 ]
     * 
* * @param predicate The {@link Closure} that stops the Stream when it returns {@code true}. * @return A new {@code Stream} wrapping an {@link UntilIterator} */ public Stream untilWithIndex( Closure predicate ) { return new Stream( new UntilIterator( iterator, predicate, true ) ) ; } /** * Calls the {@link IndexedPredicate} with the current element and the index in the stream. * When the predicate returns {@code true}, the stream is stopped. * * @param predicate The {@link IndexedPredicate} that stops the Stream when it returns {@code true}. * @return A new {@code Stream} wrapping an {@link UntilIteratorForIndexedPredicate} */ public Stream untilWithIndex( IndexedPredicate predicate ) { return new Stream( new UntilIteratorForIndexedPredicate( iterator, predicate ) ) ; } /** * Groups a the elements of a {@code Stream} into groups of length {@code size}. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..9 )
     *                .collate( 4 )
     *                .collect() == [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9 ] ]
     * 
* * @param size the size of each collated group * @return A new {@code Stream} wrapping an {@link CollatingIterator} */ public Stream> collate( int size ) { return collate( size, size, true ) ; } /** * Groups a the elements of a {@code Stream} into groups of length {@code size}. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..9 )
     *                .collate( 4, false )
     *                .collect() == [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ] ]
     * 
* * @param size the size of each collated group * @param keepRemainder Should any remaining objects be returned at the end * @return A new {@code Stream} wrapping an {@link CollatingIterator} */ public Stream> collate( int size, boolean keepRemainder ) { return collate( size, size, keepRemainder ) ; } /** * Groups a the elements of a {@code Stream} into groups of length {@code size} * using a step-size of {@code step}. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..9 )
     *                .collate( 4, 1 )
     *                .collect() == [ [ 1, 2, 3, 4 ],
     *                                [ 2, 3, 4, 5 ],
     *                                [ 3, 4, 5, 6 ],
     *                                [ 4, 5, 6, 7 ],
     *                                [ 5, 6, 7, 8 ],
     *                                [ 6, 7, 8, 9 ],
     *                                [ 7, 8, 9 ],
     *                                [ 8, 9 ],
     *                                [ 9 ] ]
     * 
* * @param size the size of each collated group * @param step How many to increment the window by each turn * @return A new {@code Stream} wrapping an {@link CollatingIterator} */ public Stream> collate( int size, int step ) { return collate( size, step, true ) ; } /** * Groups a the elements of a {@code Stream} into groups of length {@code size} * using a step-size of {@code step}. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..9 )
     *                .collate( 4, 1, false )
     *                .collect() == [ [ 1, 2, 3, 4 ],
     *                                [ 2, 3, 4, 5 ],
     *                                [ 3, 4, 5, 6 ],
     *                                [ 4, 5, 6, 7 ],
     *                                [ 5, 6, 7, 8 ],
     *                                [ 6, 7, 8, 9 ] ]
     * 
* * @param size the size of each collated group * @param step How many to increment the window by each turn * @param keepRemainder Should any remaining objects be returned at the end * @return A new {@code Stream} wrapping an {@link CollatingIterator} */ public Stream> collate( int size, int step, boolean keepRemainder ) { return new Stream>( new CollatingIterator( this.iterator, size, step, keepRemainder ) ) ; } /** * Takes another {@code Iterator} or {@code Stream} and calls the two arg {@code Closure} * to zip the two together. * *
     *   import groovy.stream.*
     *
     *   def numbers = Stream.from 1..3
     *   def letters = Stream.from 'a'..'d'
     *  
     *   assert numbers.zip( letters ) { n, l -> "$n:$l" }
     *                .collect() == [ "1:a", "2:b", "3:c" ]
     * 
* * @param The type of the secondary {@link Iterator}. * @param The type of the new {@link Iterator}. * @param other The other {@link Iterator} * @param map The 2 arg {@link Closure} to call with each next element from the Stream * @return A new {@code Stream} wrapping a {@link ZipIterator} */ public Stream zip( Iterator other, Closure map ) { return new Stream( new ZipIterator( this.iterator, other, false, map ) ) ; } public Stream zip( Iterable other, Closure map ) { return new Stream( new ZipIterator( this.iterator, other.iterator(), false, map ) ) ; } /** * Takes another {@code Iterator} or {@code Stream} and calls the two arg {@code Function2} * to zip the two together. * * @see #zip(java.util.Iterator, groovy.lang.Closure) * @param The type of the secondary {@link Iterator}. * @param The type of the new {@link Iterator}. * @param other The other {@link Iterator} * @param map The 2 arg {@link Function2} to call with each next element from the Stream * @return A new {@code Stream} wrapping a {@link ZipIteratorForFunction} */ public Stream zip( Iterator other, Function2 map ) { return new Stream( new ZipIteratorForFunction( this.iterator, other, map ) ) ; } public Stream zip( Iterable other, Function2 map ) { return new Stream( new ZipIteratorForFunction( this.iterator, other.iterator(), map ) ) ; } /** * Takes another {@code Iterator} or {@code Stream} and calls the three arg {@code Closure} * to zip the two together along with the current index. * *
     *   import groovy.stream.*
     *
     *   def numbers = Stream.from 1..3
     *   def letters = Stream.from 'a'..'d'
     *  
     *   assert numbers.zipWithIndex( letters ) { n, l, i -> "$n:$l:$i" }
     *                .collect() == [ "1:a:0", "2:b:1", "3:c:2" ]
     * 
* * @param The type of the secondary {@link Iterator}. * @param The type of the new {@link Iterator}. * @param other The other {@link Iterator} * @param map The 3 arg {@link Closure} to call with each next element from the Stream and the * current stream index * @return A new {@code Stream} wrapping a {@link ZipIterator} */ public Stream zipWithIndex( Iterator other, Closure map ) { return new Stream( new ZipIterator( this.iterator, other, true, map ) ) ; } public Stream zipWithIndex( Iterable other, Closure map ) { return new Stream( new ZipIterator( this.iterator, other.iterator(), true, map ) ) ; } /** * Takes another {@code Iterator} or {@code Stream} and calls the three arg {@link IndexedFunction2} * to zip the two together along with the current index. * * @see #zipWithIndex(java.util.Iterator, groovy.lang.Closure) * @param The type of the secondary {@link Iterator}. * @param The type of the new {@link Iterator}. * @param other The other {@link Iterator} * @param map The 3 arg {@link IndexedFunction2} to call with each next element from the Stream and the * current stream index * @return A new {@code Stream} wrapping a {@link ZipIteratorForIndexedFunction} */ public Stream zipWithIndex( Iterator other, IndexedFunction2 map ) { return new Stream( new ZipIteratorForIndexedFunction( this.iterator, other, map ) ) ; } public Stream zipWithIndex( Iterable other, IndexedFunction2 map ) { return new Stream( new ZipIteratorForIndexedFunction( this.iterator, other.iterator(), map ) ) ; } /** * When this stream completes, repeat it's output endlessly. * *
     *   import groovy.stream.*
     *
     *   def numbers = Stream.from 1..3
     *
     *   // We will just take the first 12 elements of this infinite stream
     *   assert numbers.repeat().take(12).collect() == [1,2,3,1,2,3,1,2,3,1,2,3]
     * 
* * @return A new {@code Stream} wrapping a {@link RepeatingIterator} */ public Stream repeat() { return new Stream(new RepeatingIterator(this.iterator)); } /** * This stream will repeat count times. * * If count is 0, the Stream will be empty. If 1, no repetition will be performed. * *
     *   import groovy.stream.*
     *
     *   def numbers = Stream.from(['alice', 'bob'])
     *
     *   assert numbers.repeat(2).collect() == ['alice','bob','alice','bob']
     * 
* * @param count The number of times to repeat the element in this Stream once it is exhausted. * @return A new {@code Stream} wrapping a {@link RepeatingIterator} */ public Stream repeat(int count) { return new Stream(new RepeatingIterator(this.iterator, count)); } /** * Limits the {@code Stream} to {@code n} elements. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1..9 )
     *                .take( 3 )
     *                .collect() == [ 1, 2, 3 ]
     * 
* * @param n The number of element to limit the {@code Stream} to. * @return A new {@code Stream} wrapping a {@link LimitedIterator} */ public Stream take( int n ) { return new Stream( new LimitedIterator( this.iterator, n ) ) ; } /** * Construct a {@code Stream} from a {@link Map} of Iterables. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( a:1..3, b:'a'..'c' )
     *                .collect() == [ [ a:1, b:'a' ],
     *                                [ a:1, b:'b' ],
     *                                [ a:1, b:'c' ],
     *                                [ a:2, b:'a' ],
     *                                [ a:2, b:'b' ],
     *                                [ a:2, b:'c' ],
     *                                [ a:3, b:'a' ],
     *                                [ a:3, b:'b' ],
     *                                [ a:3, b:'c' ] ]
     * 
* * @param They type of the Map keys. * @param The type of the Iterable value. * @param map The map of Iterables. * @return A new {@code Stream} wrapping a {@link MapIterator}. */ public static Stream> from( Map> map ) { return new Stream>( new MapIterator( map ) ) ; } /** * Construct a {@code Stream} from another {@code Stream}. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( Stream.from( 1..3 ) )
     *                .collect() == [ 1, 2, 3 ]
     * 
* * @param The type of the Stream. * @param stream The other {@code Stream}. * @return A new {@code Stream} wrapping the iterator of the other {@code Stream}. */ public static Stream from( Stream stream ) { return new Stream( stream.iterator ) ; } /** * Construct a {@code Stream} from an {@link Iterable}. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( [ 1, 2, 3 ] )
     *                .collect() == [ 1, 2, 3 ]
     * 
* * @param The type of the Iterable. * @param iterable The iterable to iterate. * @return A new {@code Stream} wrapping the {@code iterable.iterator()}. */ public static Stream from( Iterable iterable ) { return new Stream( iterable.iterator() ) ; } /** * Construct a {@code Stream} from an {@link Iterator}. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( [ 1, 2, 3 ].iterator() )
     *                .collect() == [ 1, 2, 3 ]
     * 
* * @param The type of the Iterator. * @param iterator The iterator to wrap. * @return A new {@code Stream} wrapping the iterator. */ public static Stream from( Iterator iterator ) { return new Stream( iterator ) ; } /** * Construct a {@code Stream} from a {@link BufferedReader} that iterates the lines in it. * * @param reader The Reader to iterate lines from * @return A new {@code Stream} wrapping a {@link BufferedReaderIterator}. */ public static Stream from( BufferedReader reader ) { return new Stream( new BufferedReaderIterator( reader ) ) ; } /** * Construct a {@code Stream} from a {@link ZipFile} that iterates the {@link ZipEntry} objects contained within. * * @param file the ZipFile to iterate ZipEntrys from. * @return A new {@code Stream} wrapping an {@link EnumerationIterator}. */ public static Stream from( ZipFile file ) { return new Stream( new EnumerationIterator( file.entries() ) ) ; } /** * Construct a {@code Stream} from a {@link JarFile} that iterates the {@link JarEntry} objects contained within. * * @param file the JarFile to iterate JarEntrys from. * @return A new {@code Stream} wrapping an {@link EnumerationIterator}. */ public static Stream from( JarFile file ) { return new Stream( new EnumerationIterator( file.entries() ) ) ; } /** * Construct a {@code Stream} that for every element, returns the result of calling the {@link Closure}. * * @param The type of the return value from the Closure. * @param closure The closure to call each time an element is requested. * @return A new {@code Stream} wrapping an {@link RepeatingClosureIterator}. */ public static Stream from( Closure closure ) { return new Stream( new RepeatingClosureIterator( closure ) ) ; } /** * Construct a {@code Stream} that for every element, returns {@code object}. * *
     *   import groovy.stream.*
     *
     *   assert Stream.from( 1 ).take( 3 ).collect() == [ 1, 1, 1 ]
     * 
* * @param The type of the {@code Object}. * @param object The object to return each time an element is requested. * @return A new {@code Stream} wrapping an {@link RepeatingObjectIterator}. */ public static Stream from( T object ) { return new Stream( new RepeatingObjectIterator( object ) ) ; } /** * Construct a {@code Stream} that iterates every {@code Object} in an array. First converts the array to an {@link ArrayList}, then wraps the {@code ArrayList.iterator()}. * *
     *   import groovy.stream.*
     *
     *   String[] elems = [ 'one', 'two', 'three' ]
     *
     *   assert Stream.from( elems ).collect() == [ 'one', 'two', 'three' ]
     * 
* * @param The type of the array. * @param array An array of Object to iterate * @return A new {@code Stream} wrapping the iterator for the array as a List. */ @SuppressWarnings("unchecked") public static Stream from( T[] array ) { return new Stream( primitiveArrayToList( array ).iterator() ) ; } /** * Construct a {@code Stream} that iterates every {@code byte} in an array. First converts the array to an {@link ArrayList}, then wraps the {@code ArrayList.iterator()}. * *
     *   import groovy.stream.*
     *
     *   byte[] elems = [ 127, 128, 129 ]
     *
     *   assert Stream.from( elems ).collect() == [ 127, -128, -127 ]
     * 
* * @param array An array of byte to iterate * @return A new {@code Stream} wrapping the iterator for the array as a List. */ @SuppressWarnings("unchecked") public static Stream from( byte[] array ) { return new Stream( primitiveArrayToList( array ).iterator() ) ; } /** * Construct a {@code Stream} that iterates every {@code Character} in an array. First converts the array to an {@link ArrayList}, then wraps the {@code ArrayList.iterator()}. * *
     *   import groovy.stream.*
     *
     *   char[] elems = 'Hello'.toList()
     *
     *   assert Stream.from( elems ).collect() == [ 'H', 'e', 'l', 'l', 'o' ]
     * 
* * @param array An array of char to iterate * @return A new {@code Stream} wrapping the iterator for the array as a List. */ @SuppressWarnings("unchecked") public static Stream from( char[] array ) { return new Stream( primitiveArrayToList( array ).iterator() ) ; } /** * Construct a {@code Stream} that iterates every {@code Short} in an array. First converts the array to an {@link ArrayList}, then wraps the {@code ArrayList.iterator()}. * *
     *   import groovy.stream.*
     *
     *   short[] elems = [ 10, 65535, 65536, 65537, 99 ]
     *
     *   assert Stream.from( elems ).collect() == [ 10, -1, 0, 1, 99 ]
     * 
* * @param array An array of short to iterate * @return A new {@code Stream} wrapping the iterator for the array as a List. */ @SuppressWarnings("unchecked") public static Stream from( short[] array ) { return new Stream( primitiveArrayToList( array ).iterator() ) ; } /** * Construct a {@code Stream} that iterates every {@code Integer} in an array. First converts the array to an {@link ArrayList}, then wraps the {@code ArrayList.iterator()}. * *
     *   import groovy.stream.*
     *
     *   int[] elems = [ 10, 65535, 65536, 65537, 99 ]
     *
     *   assert Stream.from( elems ).collect() == [ 10, 65535, 65536, 65537, 99 ]
     * 
* * @param array An array of int to iterate * @return A new {@code Stream} wrapping the iterator for the array as a List. */ @SuppressWarnings("unchecked") public static Stream from( int[] array ) { return new Stream( primitiveArrayToList( array ).iterator() ) ; } /** * Construct a {@code Stream} that iterates every {@code Long} in an array. First converts the array to an {@link ArrayList}, then wraps the {@code ArrayList.iterator()}. * *
     *   import groovy.stream.*
     *
     *   long[] elems = [ 10, 65535, 65536, 65537, 99 ]
     *
     *   assert Stream.from( elems ).collect() == [ 10, 65535, 65536, 65537, 99 ]
     * 
* * @param array An array of long to iterate * @return A new {@code Stream} wrapping the iterator for the array as a List. */ @SuppressWarnings("unchecked") public static Stream from( long[] array ) { return new Stream( primitiveArrayToList( array ).iterator() ) ; } /** * Construct a {@code Stream} that iterates every {@code Float} in an array. First converts the array to an {@link ArrayList}, then wraps the {@code ArrayList.iterator()}. * *
     *   import groovy.stream.*
     *
     *   float[] elems = [ 0.1, 0.2, 0.3 ]
     *
     *   assert Stream.from( elems ).collect() == [ 0.1f, 0.2f, 0.3f ]
     * 
* * @param array An array of float to iterate * @return A new {@code Stream} wrapping the iterator for the array as a List. */ @SuppressWarnings("unchecked") public static Stream from( float[] array ) { return new Stream( primitiveArrayToList( array ).iterator() ) ; } /** * Construct a {@code Stream} that iterates every {@code Double} in an array. First converts the array to an {@link ArrayList}, then wraps the {@code ArrayList.iterator()}. * *
     *   import groovy.stream.*
     *
     *   double[] elems = [ 0.1, 0.2, 0.3 ]
     *
     *   assert Stream.from( elems ).collect() == [ 0.1, 0.2, 0.3 ]
     * 
* * @param array An array of double to iterate * @return A new {@code Stream} wrapping the iterator for the array as a List. */ @SuppressWarnings("unchecked") public static Stream from( double[] array ) { return new Stream( primitiveArrayToList( array ).iterator() ) ; } /** * Construct a {@code Stream} that iterates every {@code Boolean} in an array. First converts the array to an {@link ArrayList}, then wraps the {@code ArrayList.iterator()}. * *
     *   import groovy.stream.*
     *
     *   boolean[] elems = [ true, false ]
     *
     *   assert Stream.from( elems ).collect() == [ true, false ]
     * 
* * @param array An array of boolean to iterate * @return A new {@code Stream} wrapping the iterator for the array as a List. */ @SuppressWarnings("unchecked") public static Stream from( boolean[] array ) { return new Stream( primitiveArrayToList( array ).iterator() ) ; } @Override public T next() { return iterator.next() ; } @Override public boolean hasNext() { return iterator.hasNext() ; } @Override public void remove() { iterator.remove() ; } /* Utilities */ @SuppressWarnings("unchecked") private static List primitiveArrayToList( Object array ) { int size = Array.getLength( array ) ; List list = new ArrayList( size ) ; for( int i = 0 ; i < size ; i++ ) { list.add( Array.get( array, i ) ) ; } return list ; } }