diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/util/NewPipeStreamCollectors.java b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/util/NewPipeStreamCollectors.java new file mode 100644 index 000000000..f9d1d03f0 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/util/NewPipeStreamCollectors.java @@ -0,0 +1,100 @@ +package org.schabi.newpipe.extractor.streamdata.stream.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collector; +import java.util.stream.Stream; + +public final class NewPipeStreamCollectors { + private NewPipeStreamCollectors() { + // No impl + } + + public static + Collector> toDistinctList() { + return deduplicateEqualStreams(x -> x); + } + + public static + Collector> toDistinctStream() { + return deduplicateEqualStreams(List::stream); + } + + public static + Collector deduplicateEqualStreams(final Function, R> finisher) { + return new CollectorImpl<>( + (Supplier>) ArrayList::new, + List::add, + (left, right) -> { + for(final T rightElement : right) { + if (NewPipeStreamUtil.containSimilarStream(rightElement, left)) { + left.add(rightElement); + } + } + return left; + }, + finisher, + CH_ID); + } + + /** + * Copied from {@link java.util.stream.Collectors} + */ + static final Set CH_ID = + Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH)); + + /** + * Copied from {@link java.util.stream.Collectors} + */ + static class CollectorImpl implements Collector { + private final Supplier supplier; + private final BiConsumer accumulator; + private final BinaryOperator combiner; + private final Function finisher; + private final Set characteristics; + + CollectorImpl(final Supplier supplier, + final BiConsumer accumulator, + final BinaryOperator combiner, + final Function finisher, + final Set characteristics) { + this.supplier = supplier; + this.accumulator = accumulator; + this.combiner = combiner; + this.finisher = finisher; + this.characteristics = characteristics; + } + + @Override + public BiConsumer accumulator() { + return accumulator; + } + + @Override + public Supplier supplier() { + return supplier; + } + + @Override + public BinaryOperator combiner() { + return combiner; + } + + @Override + public Function finisher() { + return finisher; + } + + @Override + public Set characteristics() { + return characteristics; + } + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/util/NewPipeStreamUtil.java b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/util/NewPipeStreamUtil.java new file mode 100644 index 000000000..78a62a945 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/streamdata/stream/util/NewPipeStreamUtil.java @@ -0,0 +1,38 @@ +package org.schabi.newpipe.extractor.streamdata.stream.util; + +import org.schabi.newpipe.extractor.streamdata.stream.Stream; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public final class NewPipeStreamUtil { + private NewPipeStreamUtil() { + // No impl + } + + /** + * Checks if the list already contains a stream with the same statistics. + * + * @param stream the stream to be compared against the streams in the stream list + * @param streams the list of {@link Stream}s which will be compared + * @return whether the list already contains one stream with equals stats + */ + public static boolean containSimilarStream(final Stream stream, + final Collection streams) { + if (streams == null || streams.isEmpty()) { + return false; + } + return streams.stream().anyMatch(stream::equalsStream); + } + + public List removeEqualStreams(final Collection streams) { + final List returnList = new ArrayList<>(); + for(final T stream : streams) { + if (!containSimilarStream(stream, returnList)) { + returnList.add(stream); + } + } + return returnList; + } +}