All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javaslang.collection.Collections Maven / Gradle / Ivy

/*     / \____  _    _  ____   ______  / \ ____  __    _ _____
 *    /  /    \/ \  / \/    \ /  /\__\/  //    \/  \  / /  _  \   Javaslang
 *  _/  /  /\  \  \/  /  /\  \\__\\  \  //  /\  \ /\\/  \__/  /   Copyright 2014-now Daniel Dietrich
 * /___/\_/  \_/\____/\_/  \_/\__\/__/___\_/  \_//  \__/_____/    Licensed under the Apache License, Version 2.0
 */
package javaslang.collection;

import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * Internal class, containing helpers.
 *
 * @author Daniel Dietrich
 * @since 2.0.0
 */
final class Collections {

    static  Map mergeMaps(Map map1, Map map2,
                                      Function, Map> converter) {
        Objects.requireNonNull(map2, "that is null");
        if (map1.isEmpty()) {
            return converter.apply(map2);
        } else if (map2.isEmpty()) {
            return map1;
        } else {
            return map2.foldLeft(map1, (map, entry) -> !map.containsKey(entry._1) ? map.put(entry) : map);
        }
    }

    static  Map mergeMaps(Map map1, Map map2,
                                                   Function, Map> converter,
                                                   BiFunction collisionResolution) {
        Objects.requireNonNull(map2, "that is null");
        Objects.requireNonNull(collisionResolution, "collisionResolution is null");
        if (map1.isEmpty()) {
            return converter.apply(map2);
        } else if (map2.isEmpty()) {
            return map1;
        } else {
            return map2.foldLeft(map1, (map, entry) -> {
                final K key = entry._1;
                final U value = entry._2;
                final V newValue = map.get(key).map(v -> (V) collisionResolution.apply(v, value)).getOrElse(value);
                return map.put(key, newValue);
            });
        }
    }

    static , R extends Traversable> R scanLeft(
            Iterable elements,
            U zero, BiFunction operation,
            C cumulativeResult, BiFunction combiner, Function finisher) {
        U acc = zero;
        cumulativeResult = combiner.apply(cumulativeResult, acc);
        for (T a : elements) {
            acc = operation.apply(acc, a);
            cumulativeResult = combiner.apply(cumulativeResult, acc);
        }
        return finisher.apply(cumulativeResult);
    }

    static , R extends Traversable> R scanRight(
            Iterable elements,
            U zero, BiFunction operation,
            C cumulativeResult, BiFunction combiner, Function finisher) {
        final Iterator reversedElements = seq(elements).reverseIterator();
        return scanLeft(reversedElements, zero, (u, t) -> operation.apply(t, u), cumulativeResult, combiner, finisher);
    }

    @SuppressWarnings("unchecked")
    static  Iterator> crossProduct(Seq seq, int power) {
        if (power < 0) {
            throw new IllegalArgumentException("negative power");
        }
        return Iterator
                .range(1, power)
                .foldLeft((Iterator>) seq.sliding(1), (product, ignored) -> product.flatMap(tuple -> seq.map(tuple::append)));
    }

    static , T> C tabulate(int n, Function f, C empty, Function of) {
        Objects.requireNonNull(f, "f is null");
        Objects.requireNonNull(empty, "empty is null");
        Objects.requireNonNull(of, "of is null");
        if (n <= 0) {
            return empty;
        } else {
            @SuppressWarnings("unchecked")
            T[] elements = (T[]) new Object[n];
            for (int i = 0; i < n; i++) {
                elements[i] = f.apply(i);
            }
            return of.apply(elements);
        }
    }

    static , T> C fill(int n, Supplier s, C empty, Function of) {
        Objects.requireNonNull(s, "s is null");
        Objects.requireNonNull(empty, "empty is null");
        Objects.requireNonNull(of, "of is null");
        return tabulate(n, anything -> s.get(), empty, of);
    }

    static  Iterator tabulate(int n, Function f) {
        Objects.requireNonNull(f, "f is null");
        if (n <= 0) {
            return Iterator.empty();
        } else {
            return new AbstractIterator() {

                int i = 0;

                @Override
                public boolean hasNext() {
                    return i < n;
                }

                @Override
                protected T getNext() {
                    return f.apply(i++);
                }
            };
        }
    }

    static  Iterator fill(int n, Supplier s) {
        Objects.requireNonNull(s, "s is null");
        return tabulate(n, anything -> s.get());
    }

    @SuppressWarnings("unchecked")
    private static  Seq seq(Iterable iterable) {
        if (iterable instanceof Seq) {
            return (Seq) iterable;
        } else {
            return List.ofAll(iterable);
        }
    }
}