Skip to content

Instantly share code, notes, and snippets.

@timyates
Last active May 30, 2016 08:32
Show Gist options
  • Save timyates/8686020 to your computer and use it in GitHub Desktop.
Save timyates/8686020 to your computer and use it in GitHub Desktop.
Implementing Groovy's collate method in Java 8 Streams
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/* Efficiency must be questioned
*
* Also, no error checking, so could go infinite if called with dodgy params
*
* (left as an exercise for the reader) ;-)
*/
public class Collate {
public <T> List<List<T>> collate( List<T> list, int size, int step ) {
return Stream.iterate( 0, i -> i + step )
.limit( ( list.size() / step ) + 1 )
.map( i -> list.stream()
.skip( i )
.limit( size )
.collect( Collectors.toList() ) )
.filter( i -> !i.isEmpty() )
.collect( Collectors.toList() ) ;
}
public static void main( String[] args ) {
Collate c = new Collate() ;
List<Integer> test = Arrays.asList( 1, 2, 3, 4, 5, 6, 7, 8, 9 ) ;
// Prints [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7, 8], [7, 8, 9], [8, 9], [9]]
System.out.println( c.collate( test, 3, 1 ) ) ;
// Prints [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9]]
System.out.println( c.collate( test, 3, 2 ) ) ;
// Prints [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
System.out.println( c.collate( test, 3, 3 ) ) ;
}
}
@timyates
Copy link
Author

@mperry Does this look right for the unfold method?

    class Pair<T,U> {
        private final T left ;
        private final U right ;

        public Pair( T left, U right ) {
            this.left = left ;
            this.right = right ;
        }

        public T getLeft()  { return left; }
        public U getRight() { return right; }
    }

    private <T,U> List<T> unfold( U val, Function<U,Optional<Pair<T,U>>> f ) {
        List<T> ret = new ArrayList<>() ;
        while( true ) {
            Optional<Pair<T,U>> r = f.apply( val ) ;
            if( !r.isPresent() ) {
                break ;
            }
            Pair<T,U> o = r.get() ;
            ret.add( o.getLeft() ) ;
            val = o.getRight() ;
        }
        return ret ;
    }

    public <T> List<List<T>> collate2( List<T> list, int size, int step ) {
        return unfold( list, i -> 
                i.isEmpty() ? 
                    Optional.empty() : 
                    Optional.of( new Pair<>( i.subList( 0, Math.min( size, i.size() ) ),
                                             i.subList( Math.min( step, i.size() ), i.size() ) ) ) ) ;
    }

@mperry
Copy link

mperry commented Jan 30, 2014

Looks about right. Is this exactly the same implementation as above, in particular the need for Math.min? I could probably figure it out myself, but don't have the time at the moment to. Pair implementation looks ok, unfortunately Java does not support any tuple type. As an aside, I got FunctionalJava working with Java 8, I will have to get this organised soon - best to use FJ's P (product type) to produce a P2 for the pair. On this point, I would add a static method to produce the pair, to get rid of the ugly instantiation.

@timyates
Copy link
Author

Without Math.min, sublist walks off the end of the list when you get near the end :-(

Yeah, I think people have been asking for java.util.Pair for a long time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment