silentbalanceyh/vertx-zero

View on GitHub
vertx-gaia/vertx-ams/src/main/java/io/horizon/util/CArithmetic.java

Summary

Maintainability
A
1 hr
Test Coverage
package io.horizon.util;

import io.horizon.uca.compare.Vs;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;

/**
 * Collection calculation for Set
 * Here List is not needed for this arithmetic because all the calculation method require your
 * collection support non-duplicated and non-sequence.
 */
final class CArithmetic {
    private CArithmetic() {
    }

    /**
     * Collection intersect ( HashSet / TreeSet )
     * A = {1, 2}
     * B = {1, 3}
     * The result should be {1}
     *
     * @param left  First Set
     * @param right Second Set
     * @param <T>   The element type in Set
     *
     * @return The result set
     */
    static <T> Set<T> intersect(final Set<T> left,
                                final Set<T> right) {
        final Set<T> ret = new HashSet<>(left);
        ret.retainAll(right);
        return ret;
    }

    /*
     * Collection intersect ( HashSet / TreeSet )
     *
     * @param left First Set
     * @param right Second Set
     * @param fnGet The method of java bean
     * @param <T> The element entity type in Set
     *
     * @return The result set
     */
    static <T, V> Set<T> intersect(final Set<T> left, final Set<T> right, final Function<T, V> fnGet) {
        /*
         * Iterate left to pick up that element in right
         */
        final Set<T> result = new HashSet<>();
        left.stream()
            .map(original -> findBy(right, original, fnGet))
            .filter(Objects::nonNull)
            .forEach(result::add);
        return result;
    }

    /**
     * Collection union ( HashSet / TreeSet )
     * A = {1, 2}
     * B = {1, 3}
     * The result should be {1, 2, 3}
     *
     * @param left  First Set
     * @param right Second Set
     * @param <T>   The element type in Set
     *
     * @return The result Set
     */
    static <T> Set<T> union(final Set<T> left,
                            final Set<T> right) {
        final Set<T> ret = new HashSet<>();
        ret.addAll(left);
        ret.addAll(right);
        return ret;
    }

    static <T, V> Set<T> union(final Set<T> left, final Set<T> right, final Function<T, V> fnGet) {
        final Set<T> result = new HashSet<>(left);
        right.forEach(original -> {
            /*
             * Search T in `left`
             * If returned reference is null, means that original could be added
             * into result because `original` belong to `right` but not belong to `left`
             */
            final T found = findBy(left, original, fnGet);
            if (Objects.isNull(found)) {
                result.add(original);
            }
        });
        return result;
    }

    /**
     * Collection removing ( HashSet / TreeSet )
     * A = {1, 2}
     * B = {1, 3}
     * The result should be {2}
     *
     * @param subtrahend Subtrahend set
     * @param minuend    Minuend set
     * @param <T>        The element type in Set
     *
     * @return The result SEt
     */
    static <T> Set<T> diff(final Set<T> subtrahend,
                           final Set<T> minuend) {
        final Set<T> ret = new HashSet<>(subtrahend);
        ret.removeAll(minuend);
        return ret;
    }

    static <T, V> Set<T> diff(final Set<T> subtrahend, final Set<T> minuend, final Function<T, V> fnGet) {
        final Set<T> result = new HashSet<>();
        subtrahend.forEach(original -> {
            final T found = findBy(minuend, original, fnGet);
            if (Objects.isNull(found)) {
                result.add(original);
            }
        });
        return result;
    }

    private static <T, V> T findBy(final Set<T> source, final T original, final Function<T, V> fnGet) {
        return source.stream()
            .filter(current -> Vs.isSame(original, current, fnGet))
            .findAny().orElse(null);
    }
}