Skip to content

Instantly share code, notes, and snippets.

@VAlux
Created June 5, 2021 08:44
Show Gist options
  • Save VAlux/3a314d488c3082a2685ff97f475adb73 to your computer and use it in GitHub Desktop.
Save VAlux/3a314d488c3082a2685ff97f475adb73 to your computer and use it in GitHub Desktop.
Java collections/streams handy operations
/**
* Basic folding of the specified iterable source seeded with initial value and accumulated by the
* provided operation
*/
public static <T, R> R fold(final Iterable<T> source,
final R initial,
final BiFunction<R, T, R> operation) {
var accumulator = initial;
for (T element : source) {
accumulator = operation.apply(accumulator, element);
}
return accumulator;
}
public static <T, R> R fold(final Stream<T> source,
final R initial,
final BiFunction<R, T, R> operation) {
final var accumulator = new AtomicReference<>(initial);
source.forEach(element -> {
final var current = accumulator.get();
accumulator.compareAndSet(current, operation.apply(current, element));
});
return accumulator.get();
}
/**
* Zip specified collection into a list of pairs, where first component is represented by current
* element and the second component is the corresponding elements index.
*
* Example: zipWithIndex(List.of("one", "two", "three"))
*
* is an equivalent to:
*
* List.of(Pair.of("one", 0), Pair.of("two", 1), Pair.of("three", 2)))
*/
public static <T> List<Pair<T, Integer>> zipWithIndex(final Collection<T> source) {
return fold(source, new ArrayList<>(), (current, item) -> {
current.add(Pair.of(item, current.size()));
return current;
});
}
/**
* Zip specified stream into a stream of pairs, where first component is represented by current
* element and the second component is the corresponding elements index.
*
* Example: zipWithIndex(Stream.of("one", "two", "three"))
*
* is an equivalent to:
*
* Stream.of(Pair.of("one", 0), Pair.of("two", 1), Pair.of("three", 2)))
*/
public static <T> Stream<Pair<T, Integer>> zipWithIndex(final Stream<T> source) {
final var size = new AtomicInteger(0);
return fold(source, Stream.empty(), (current, item) ->
Stream.concat(current, Stream.of(Pair.of(item, size.getAndIncrement()))));
}
/**
* Partition list into list of chunks of specified size
*/
public static <T> List<List<T>> partition(final List<T> source, final int chunkSize) {
return fold(source, new ArrayList<>(), (current, item) -> {
if (current.isEmpty() || current.get(current.size() - 1).size() % chunkSize == 0) {
current.add(new ArrayList<>());
}
current.get(current.size() - 1).add(item);
return current;
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment