red6/dmn-check

View on GitHub
validators/src/main/java/de/redsix/dmncheck/util/Util.java

Summary

Maintainability
A
2 hrs
Test Coverage
package de.redsix.dmncheck.util;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.BiFunction;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public final class Util {

    private Util() {}

    public static <A, B, C> Stream<C> zip(
            final Stream<? extends A> a,
            final Stream<? extends B> b,
            final BiFunction<? super A, ? super B, ? extends C> zipper) {
        Objects.requireNonNull(zipper);
        final Spliterator<? extends A> aSpliterator = Objects.requireNonNull(a).spliterator();
        final Spliterator<? extends B> bSpliterator = Objects.requireNonNull(b).spliterator();

        // Zipping looses DISTINCT and SORTED characteristics
        final int characteristics = aSpliterator.characteristics()
                & bSpliterator.characteristics()
                & ~(Spliterator.DISTINCT | Spliterator.SORTED);

        final long zipSize = ((characteristics & Spliterator.SIZED) != 0)
                ? Math.min(aSpliterator.getExactSizeIfKnown(), bSpliterator.getExactSizeIfKnown())
                : -1;

        final Iterator<A> aIterator = Spliterators.iterator(aSpliterator);
        final Iterator<B> bIterator = Spliterators.iterator(bSpliterator);
        final Iterator<C> cIterator = new Iterator<>() {

            @Override
            public boolean hasNext() {
                return aIterator.hasNext() && bIterator.hasNext();
            }

            @Override
            public C next() {
                return zipper.apply(aIterator.next(), bIterator.next());
            }
        };

        final Spliterator<C> split = Spliterators.spliterator(cIterator, zipSize, characteristics);
        return (a.isParallel() || b.isParallel())
                ? StreamSupport.stream(split, true)
                : StreamSupport.stream(split, false);
    }

    public static <A, B, C, D> Stream<D> zip(
            final Stream<? extends A> a,
            final Stream<? extends B> b,
            final Stream<? extends C> c,
            final TriFunction<? super A, ? super B, ? super C, ? extends D> zipper) {
        Objects.requireNonNull(zipper);
        final Spliterator<? extends A> aSpliterator = Objects.requireNonNull(a).spliterator();
        final Spliterator<? extends B> bSpliterator = Objects.requireNonNull(b).spliterator();
        final Spliterator<? extends C> cSpliterator = Objects.requireNonNull(c).spliterator();

        // Zipping looses DISTINCT and SORTED characteristics
        final int characteristics = aSpliterator.characteristics()
                & bSpliterator.characteristics()
                & cSpliterator.characteristics()
                & ~(Spliterator.DISTINCT | Spliterator.SORTED);

        final long zipSize = ((characteristics & Spliterator.SIZED) != 0)
                ? Math.min(
                        aSpliterator.getExactSizeIfKnown(),
                        Math.min(bSpliterator.getExactSizeIfKnown(), cSpliterator.getExactSizeIfKnown()))
                : -1;

        final Iterator<A> aIterator = Spliterators.iterator(aSpliterator);
        final Iterator<B> bIterator = Spliterators.iterator(bSpliterator);
        final Iterator<C> cIterator = Spliterators.iterator(cSpliterator);

        final Iterator<D> dIterator = new Iterator<>() {

            @Override
            public boolean hasNext() {
                return aIterator.hasNext() && bIterator.hasNext() && cIterator.hasNext();
            }

            @Override
            public D next() {
                return zipper.apply(aIterator.next(), bIterator.next(), cIterator.next());
            }
        };

        final Spliterator<D> split = Spliterators.spliterator(dIterator, zipSize, characteristics);
        return (a.isParallel() || b.isParallel() || c.isParallel())
                ? StreamSupport.stream(split, true)
                : StreamSupport.stream(split, false);
    }
}