-
-
Save timyates/8686020 to your computer and use it in GitHub Desktop.
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 ) ) ; | |
} | |
} |
You might like to write unfold for Streams in Java 8 using "of" and "concat". Implementing collate using unfold is easier and far more concise, as you saw in my implementation.
You should be able to use Stream.iterate instead of generate to simplify things, something like:
iterate(step, i-> i + step)
@mperry I wish gists emailled me when a comment was added ;-)
Cool! Added the Stream.iterate
(I'd not seen that before, very nice), and I'll look onto unfold
now :-D
@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() ) ) ) ) ;
}
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.
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
Hat-tip (as usual) to @mperry
https://github.com/mperry/functionalgroovy/blob/master/core/src/test/groovy/com/github/mperry/fg/test/ListJavaExtensionTest.groovy