Skip to content

Instantly share code, notes, and snippets.

@AFutureD
Created April 10, 2024 09:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AFutureD/adb0721e4b2e6a8cf02c2ef925bf1b22 to your computer and use it in GitHub Desktop.
Save AFutureD/adb0721e4b2e6a8cf02c2ef925bf1b22 to your computer and use it in GitHub Desktop.
package ;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static java.lang.Math.min;
public class CollStreamUtil extends cn.hutool.core.collection.CollStreamUtil {
public static <E, T> List<T> flatten(Collection<E> collection, Function<E, Collection<T>> function) {
if (CollectionUtil.isEmpty(collection)) {
return Collections.emptyList();
}
return collection.stream()
.map(function)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
public static <U, E> E max(Collection<E> collection, Comparator<? super E> comparator) {
if (CollectionUtil.isEmpty(collection)) {
return null;
}
return collection.stream()
.max(comparator)
.orElse(null);
}
public static <U extends Comparable<? super U>, E> E max(Collection<E> collection, Function<? super E, U> keyExtractor) {
if (CollectionUtil.isEmpty(collection)) {
return null;
}
return collection.stream()
.max(Comparator.comparing(keyExtractor))
.orElse(null);
}
public static <E> List<E> distinct(Collection<E> collection) {
if (CollectionUtil.isEmpty(collection)) {
return Collections.emptyList();
}
return collection.stream()
.distinct()
.collect(Collectors.toList());
}
public static <T> int sumInt(Collection<T> collection, Function<T, Integer> predicate) {
if (CollectionUtil.isEmpty(collection)) {
return 0;
}
return collection.stream()
.map(predicate)
.filter(Objects::nonNull)
.reduce(0, Integer::sum);
}
public static <T> T first(Collection<T> collection) {
if (CollectionUtil.isEmpty(collection)) {
return null;
}
return collection.stream()
.findFirst()
.orElse(null);
}
public static <U, T> Collection<U> withPrevious(Collection<T> collection, BiFunction<? super T, ? super T, U> function) {
ArrayList<T> values = new ArrayList<>(collection);
values.add(0, null);
return zip(values, collection, function).collect(Collectors.toList());
}
public static <U, A> List<U> reduceMap(Collection<A> collectA, BiFunction<U, A, U> function) {
if (collectA == null || function == null) {
throw new NullPointerException();
}
Stream<A> streamA = collectA.stream();
Spliterator<A> splitrA = streamA.spliterator();
int characteristics = splitrA.characteristics() & (Spliterator.SIZED | Spliterator.ORDERED);
Iterator<A> itrA = Spliterators.iterator(splitrA);
Stream<U> closedStream = StreamSupport.stream(
new Spliterators.AbstractSpliterator<U>(splitrA.estimateSize(), characteristics) {
private U previous = null;
@Override
public boolean tryAdvance(Consumer<? super U> action) {
if (!itrA.hasNext()) {
return false;
}
U current = function.apply(previous, itrA.next());
action.accept(current);
previous = current;
return true;
}
},
false // not allow parallel
)
.onClose(streamA::close);
return closedStream.collect(Collectors.toList());
}
public static <A, B, R> Stream<R> zip(Collection<A> collectA, Collection<B> collectB, BiFunction<? super A, ? super B, R> function) {
if (collectA == null || collectB == null || function == null) {
throw new NullPointerException();
}
Stream<A> streamA = collectA.stream();
Stream<B> streamB = collectB.stream();
boolean isParallel = streamA.isParallel() || streamB.isParallel(); // same as Stream.concat
Spliterator<A> splitrA = streamA.spliterator();
Spliterator<B> splitrB = streamB.spliterator();
int characteristics = splitrA.characteristics() & splitrB.characteristics() & (Spliterator.SIZED | Spliterator.ORDERED);
Iterator<A> itrA = Spliterators.iterator(splitrA);
Iterator<B> itrB = Spliterators.iterator(splitrB);
return StreamSupport.stream(new Spliterators.AbstractSpliterator<R>(
min(splitrA.estimateSize(), splitrB.estimateSize()), characteristics) {
@Override
public boolean tryAdvance(Consumer<? super R> action) {
if (itrA.hasNext() && itrB.hasNext()) {
action.accept(function.apply(itrA.next(), itrB.next()));
return true;
}
return false;
}
},
isParallel
)
.onClose(streamA::close)
.onClose(streamB::close);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment