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

net.morimekta.collect.UnmodifiableSortedMap Maven / Gradle / Ivy

Go to download

Unmodifiable collections for java. These collections have some specific behavior criteria that is currently not guaranteed by the native java unmodifiable collections, they are also set up with convenient builders.

There is a newer version: 5.0.0
Show newest version
/*
 * Copyright (C) 2018 Stein Eldar Johnsen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.morimekta.collect;

import net.morimekta.collect.collectors.UnmodifiableSortedMapCollector;

import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedMap;
import java.util.function.Function;
import java.util.stream.Collector;

import static java.lang.Math.max;
import static java.util.Arrays.copyOfRange;
import static java.util.Objects.requireNonNull;

/**
 * A shallow unmodifiable sorted map. Sorting will be done on instance creation.
 *
 * @param  The map key type.
 * @param  The map value type.
 */
public final class UnmodifiableSortedMap
        extends UnmodifiableMapBase
        implements SortedMap {
    // -------- Collectors --------

    /**
     * @param toKey Function to map entry to key.
     * @param    The map key type.
     * @param    The map value type.
     * @return The sorted map collector.
     */
    public static , V>
    Collector>
    toSortedMap(Function toKey) {
        return new UnmodifiableSortedMapCollector<>(toKey, v -> v, null);
    }

    /**
     * @param toKey   Function to map entry to key.
     * @param toValue Function to map entry to value.
     * @param      The map key type.
     * @param      The map value type.
     * @param      The stream entry type.
     * @return The sorted map collector.
     */
    public static , V, E>
    Collector>
    toSortedMap(Function toKey, Function toValue) {
        return new UnmodifiableSortedMapCollector<>(toKey, toValue, null);
    }

    /**
     * @param toKey      Function to map entry to key.
     * @param comparator Key comparator to sort map by.
     * @param         The map key type.
     * @param         The map value type.
     * @return The sorted map collector.
     */
    public static  Collector>
    toSortedMap(Function toKey, Comparator comparator) {
        return new UnmodifiableSortedMapCollector<>(toKey, v -> v, comparator);
    }

    /**
     * @param toKey      Function to map entry to key.
     * @param toValue    Function to map entry to value.
     * @param comparator Key comparator to sort map by.
     * @param         The map key type.
     * @param         The map value type.
     * @param         The stream entry type.
     * @return The sorted map collector.
     */
    public static  Collector>
    toSortedMap(Function toKey,
                Function toValue,
                Comparator comparator) {
        return new UnmodifiableSortedMapCollector<>(toKey, toValue, comparator);
    }

    // -------- Constructors --------

    /**
     * @param map    Map to make sorted map of.
     * @param     The map key type.
     * @param The map value type.
     * @return The unmodifiable sorted map.
     */
    public static  UnmodifiableSortedMap asSortedMap(Map map) {
        if (map.isEmpty() && !(map instanceof SortedMap)) {
            return sortedMapOf();
        }
        if (map instanceof UnmodifiableSortedMap) {
            return (UnmodifiableSortedMap) map;
        }
        Comparator comparator = null;
        if (map instanceof SortedMap) {
            comparator = ((SortedMap) map).comparator();
        }
        UnmodifiableSortedMap.Builder builder = new Builder<>(map.size(), comparator);
        builder.putAll(map);
        return builder.build();
    }

    /**
     * @param  The map key type.
     * @param  The map value type.
     * @return The unmodifiable sorted empty map.
     */
    @SuppressWarnings("unchecked")
    public static  UnmodifiableSortedMap sortedMapOf() {
        return (UnmodifiableSortedMap) EMPTY;
    }

    /**
     * @param key   The map entry key.
     * @param value The map entry value.
     * @param    The map key type.
     * @param    The map values type.
     * @return The unmodifiable sorted singleton map.
     */
    public static  UnmodifiableSortedMap sortedMapOf(K key, V value) {
        return construct(entry(key, value));
    }

    /**
     * @param k1  The first map entry key.
     * @param v1  The first map entry value.
     * @param k2  The second map entry key.
     * @param v2  The second map entry value.
     * @param  The map key type.
     * @param  The map values type.
     * @return The unmodifiable sorted map.
     */
    public static  UnmodifiableSortedMap sortedMapOf(K k1, V v1,
                                                                 K k2, V v2) {
        return construct(entry(k1, v1), entry(k2, v2));
    }

    /**
     * @param k1  The first map entry key.
     * @param v1  The first map entry value.
     * @param k2  The second map entry key.
     * @param v2  The second map entry value.
     * @param k3  The third map entry key.
     * @param v3  The third map entry value.
     * @param  The map key type.
     * @param  The map values type.
     * @return The unmodifiable sorted map.
     */
    public static  UnmodifiableSortedMap sortedMapOf(K k1, V v1,
                                                                 K k2, V v2,
                                                                 K k3, V v3) {
        return construct(entry(k1, v1), entry(k2, v2), entry(k3, v3));
    }

    /**
     * @param k1  The first map entry key.
     * @param v1  The first map entry value.
     * @param k2  The second map entry key.
     * @param v2  The second map entry value.
     * @param k3  The third map entry key.
     * @param v3  The third map entry value.
     * @param k4  The fourth map entry key.
     * @param v4  The fourth map entry value.
     * @param  The map key type.
     * @param  The map values type.
     * @return The unmodifiable sorted map.
     */
    public static  UnmodifiableSortedMap sortedMapOf(K k1, V v1,
                                                                 K k2, V v2,
                                                                 K k3, V v3,
                                                                 K k4, V v4) {
        return construct(entry(k1, v1), entry(k2, v2), entry(k3, v3), entry(k4, v4));
    }

    /**
     * @param k1  The first map entry key.
     * @param v1  The first map entry value.
     * @param k2  The second map entry key.
     * @param v2  The second map entry value.
     * @param k3  The third map entry key.
     * @param v3  The third map entry value.
     * @param k4  The fourth map entry key.
     * @param v4  The fourth map entry value.
     * @param k5  The fifth map entry key.
     * @param v5  The fifth map entry value.
     * @param  The map key type.
     * @param  The map values type.
     * @return The unmodifiable sorted map.
     */
    public static  UnmodifiableSortedMap sortedMapOf(K k1, V v1,
                                                                 K k2, V v2,
                                                                 K k3, V v3,
                                                                 K k4, V v4,
                                                                 K k5, V v5) {
        return construct(entry(k1, v1), entry(k2, v2), entry(k3, v3), entry(k4, v4), entry(k5, v5));
    }

    /**
     * @param k1  The first map entry key.
     * @param v1  The first map entry value.
     * @param k2  The second map entry key.
     * @param v2  The second map entry value.
     * @param k3  The third map entry key.
     * @param v3  The third map entry value.
     * @param k4  The fourth map entry key.
     * @param v4  The fourth map entry value.
     * @param k5  The fifth map entry key.
     * @param v5  The fifth map entry value.
     * @param k6  The sixth map entry key.
     * @param v6  The sixth map entry value.
     * @param  The map key type.
     * @param  The map values type.
     * @return The unmodifiable sorted map.
     */
    public static  UnmodifiableSortedMap sortedMapOf(K k1, V v1,
                                                                 K k2, V v2,
                                                                 K k3, V v3,
                                                                 K k4, V v4,
                                                                 K k5, V v5,
                                                                 K k6, V v6) {
        return construct(entry(k1, v1),
                         entry(k2, v2),
                         entry(k3, v3),
                         entry(k4, v4),
                         entry(k5, v5),
                         entry(k6, v6));
    }

    /**
     * @param k1  The first map entry key.
     * @param v1  The first map entry value.
     * @param k2  The second map entry key.
     * @param v2  The second map entry value.
     * @param k3  The third map entry key.
     * @param v3  The third map entry value.
     * @param k4  The fourth map entry key.
     * @param v4  The fourth map entry value.
     * @param k5  The fifth map entry key.
     * @param v5  The fifth map entry value.
     * @param k6  The sixth map entry key.
     * @param v6  The sixth map entry value.
     * @param k7  The seventh map entry key.
     * @param v7  The seventh map entry value.
     * @param  The map key type.
     * @param  The map values type.
     * @return The unmodifiable sorted map.
     */
    public static  UnmodifiableSortedMap sortedMapOf(K k1, V v1,
                                                                 K k2, V v2,
                                                                 K k3, V v3,
                                                                 K k4, V v4,
                                                                 K k5, V v5,
                                                                 K k6, V v6,
                                                                 K k7, V v7) {
        return construct(entry(k1, v1),
                         entry(k2, v2),
                         entry(k3, v3),
                         entry(k4, v4),
                         entry(k5, v5),
                         entry(k6, v6),
                         entry(k7, v7));
    }

    /**
     * @param k1  The first map entry key.
     * @param v1  The first map entry value.
     * @param k2  The second map entry key.
     * @param v2  The second map entry value.
     * @param k3  The third map entry key.
     * @param v3  The third map entry value.
     * @param k4  The fourth map entry key.
     * @param v4  The fourth map entry value.
     * @param k5  The fifth map entry key.
     * @param v5  The fifth map entry value.
     * @param k6  The sixth map entry key.
     * @param v6  The sixth map entry value.
     * @param k7  The seventh map entry key.
     * @param v7  The seventh map entry value.
     * @param k8  The eighth map entry key.
     * @param v8  The eighth map entry value.
     * @param  The map key type.
     * @param  The map values type.
     * @return The unmodifiable sorted map.
     */
    public static  UnmodifiableSortedMap sortedMapOf(K k1, V v1,
                                                                 K k2, V v2,
                                                                 K k3, V v3,
                                                                 K k4, V v4,
                                                                 K k5, V v5,
                                                                 K k6, V v6,
                                                                 K k7, V v7,
                                                                 K k8, V v8) {
        return construct(entry(k1, v1),
                         entry(k2, v2),
                         entry(k3, v3),
                         entry(k4, v4),
                         entry(k5, v5),
                         entry(k6, v6),
                         entry(k7, v7),
                         entry(k8, v8));
    }

    /**
     * @param k1  The first map entry key.
     * @param v1  The first map entry value.
     * @param k2  The second map entry key.
     * @param v2  The second map entry value.
     * @param k3  The third map entry key.
     * @param v3  The third map entry value.
     * @param k4  The fourth map entry key.
     * @param v4  The fourth map entry value.
     * @param k5  The fifth map entry key.
     * @param v5  The fifth map entry value.
     * @param k6  The sixth map entry key.
     * @param v6  The sixth map entry value.
     * @param k7  The seventh map entry key.
     * @param v7  The seventh map entry value.
     * @param k8  The eighth map entry key.
     * @param v8  The eighth map entry value.
     * @param k9  The ninth map entry key.
     * @param v9  The ninth map entry value.
     * @param  The map key type.
     * @param  The map values type.
     * @return The unmodifiable sorted map.
     */
    public static  UnmodifiableSortedMap sortedMapOf(K k1, V v1,
                                                                 K k2, V v2,
                                                                 K k3, V v3,
                                                                 K k4, V v4,
                                                                 K k5, V v5,
                                                                 K k6, V v6,
                                                                 K k7, V v7,
                                                                 K k8, V v8,
                                                                 K k9, V v9) {
        return construct(entry(k1, v1),
                         entry(k2, v2),
                         entry(k3, v3),
                         entry(k4, v4),
                         entry(k5, v5),
                         entry(k6, v6),
                         entry(k7, v7),
                         entry(k8, v8),
                         entry(k9, v9));
    }

    /**
     * @param k1  The first map entry key.
     * @param v1  The first map entry value.
     * @param k2  The second map entry key.
     * @param v2  The second map entry value.
     * @param k3  The third map entry key.
     * @param v3  The third map entry value.
     * @param k4  The fourth map entry key.
     * @param v4  The fourth map entry value.
     * @param k5  The fifth map entry key.
     * @param v5  The fifth map entry value.
     * @param k6  The sixth map entry key.
     * @param v6  The sixth map entry value.
     * @param k7  The seventh map entry key.
     * @param v7  The seventh map entry value.
     * @param k8  The eighth map entry key.
     * @param v8  The eighth map entry value.
     * @param k9  The ninth map entry key.
     * @param v9  The ninth map entry value.
     * @param k10 The tenth map entry key.
     * @param v10 The tenth map entry value.
     * @param  The map key type.
     * @param  The map values type.
     * @return The unmodifiable sorted map.
     */
    public static  UnmodifiableSortedMap sortedMapOf(K k1, V v1,
                                                                 K k2, V v2,
                                                                 K k3, V v3,
                                                                 K k4, V v4,
                                                                 K k5, V v5,
                                                                 K k6, V v6,
                                                                 K k7, V v7,
                                                                 K k8, V v8,
                                                                 K k9, V v9,
                                                                 K k10, V v10) {
        return construct(entry(k1, v1),
                         entry(k2, v2),
                         entry(k3, v3),
                         entry(k4, v4),
                         entry(k5, v5),
                         entry(k6, v6),
                         entry(k7, v7),
                         entry(k8, v8),
                         entry(k9, v9),
                         entry(k10, v10));
    }

    /**
     * @param comparator Comparator to sort entries by.
     * @param         The map key type.
     * @param         The map value type.
     * @return The sorted map builder.
     */
    public static  Builder newBuilderOrderedBy(Comparator comparator) {
        return new Builder<>(4, comparator);
    }

    /**
     * @param initialCapacity Initial capacity of builder.
     * @param comparator      Comparator to sort entries by.
     * @param              The map key type.
     * @param              The map value type.
     * @return The sorted map builder.
     */
    public static  Builder newBuilderOrderedBy(int initialCapacity, Comparator comparator) {
        return new Builder<>(max(1, initialCapacity), comparator);
    }

    /**
     * @param  The map key type.
     * @param  The map value type.
     * @return The sorted map builder using natural order.
     */
    public static , V> Builder newBuilderNaturalOrder() {
        return new Builder<>(4, null);
    }

    /**
     * @param initialCapacity Initial capacity of builder.
     * @param              The map key type.
     * @param              The map value type.
     * @return The sorted map builder using natural order.
     */
    public static , V> Builder newBuilderNaturalOrder(int initialCapacity) {
        return new Builder<>(max(1, initialCapacity), null);
    }

    /**
     * @param  The map key type.
     * @param  The map value type.
     * @return The sorted map builder using reverse order.
     */
    public static , V> Builder newBuilderReverseOrder() {
        return new Builder<>(4, Comparator.reverseOrder());
    }

    /**
     * @param initialCapacity Initial capacity of builder.
     * @param              The map key type.
     * @param              The map value type.
     * @return The sorted map builder using reverse order.
     */
    public static , V> Builder newBuilderReverseOrder(int initialCapacity) {
        return new Builder<>(max(1, initialCapacity), Comparator.reverseOrder());
    }

    // -------- Map --------

    @Override
    @SuppressWarnings("unchecked")
    public boolean containsKey(Object o) {
        return findIndex((K) o) >= 0;
    }

    @Override
    @SuppressWarnings("unchecked")
    public V get(Object o) {
        Entry entry = find((K) o);
        if (entry != null) {
            return entry.getValue();
        }
        return null;
    }

    // -------- SortedMap --------

    @Override
    public Comparator comparator() {
        return comparator;
    }

    @Override
    public UnmodifiableSortedMap subMap(K start, K end) {
        int si = findIndex(start);
        if (si < 0) {
            si = -1 - si;
        }
        int ei = findIndex(end);
        if (ei < 0) {
            ei = -1 - ei;
        }
        int len = ei - si;
        if (len <= 0) {
            return sortedMapOf();
        }
        if (si == 0 && ei == size) {
            return this;
        }
        if (si == 0) {
            return new UnmodifiableSortedMap<>(len, entries, comparator, entryComparator);
        }
        return new UnmodifiableSortedMap<>(len, copyOfRange(entries, si, ei), comparator, entryComparator);
    }

    @Override
    public UnmodifiableSortedMap headMap(K end) {
        int ei = findIndex(end);
        if (ei < 0) {
            ei = -1 - ei;
        }
        if (ei == 0) {
            return sortedMapOf();
        }
        if (ei == size) {
            return this;
        }
        return new UnmodifiableSortedMap<>(ei, entries, comparator, entryComparator);
    }

    @Override
    public UnmodifiableSortedMap tailMap(K start) {
        int si = findIndex(start);
        if (si < 0) {
            si = -1 - si;
        }
        if (si == 0) {
            return this;
        }
        int len = size - si;
        if (len <= 0) {
            return sortedMapOf();
        }
        return new UnmodifiableSortedMap<>(len, copyOfRange(entries, si, size), comparator, entryComparator);
    }

    @Override
    public K firstKey() {
        if (size == 0) {
            throw new NoSuchElementException("size == 0");
        }
        return entries[0].getKey();
    }

    @Override
    public K lastKey() {
        if (size == 0) {
            throw new NoSuchElementException("size == 0");
        }
        return entries[size - 1].getKey();
    }

    // -------- UnmodifiableMapBase --------

    @Override
    public UnmodifiableSortedMap withEntry(K key, V value) {
        requireNonNull(key, "key == null");
        requireNonNull(value, "value == null");
        if (isEmpty()) {
            if (comparator != null) {
                return UnmodifiableSortedMap.newBuilderOrderedBy(1, comparator)
                                            .put(key, value)
                                            .build();
            }
            return sortedMapOf(key, value);
        }
        return new UnmodifiableSortedMap.Builder(size + 1, comparator)
                .putAll(this)
                .put(key, value)
                .build();
    }

    @Override
    @SuppressWarnings("unchecked")
    public UnmodifiableSortedMap withEntries(Map map) {
        requireNonNull(map, "map == null");
        if (map.isEmpty()) {
            return this;
        }
        if (isEmpty()) {
            if (comparator != null) {
                return UnmodifiableSortedMap.newBuilderOrderedBy(map.size(), comparator)
                                            .putAll(map)
                                            .build();
            }
            return asSortedMap((Map) map);
        }
        return new UnmodifiableSortedMap.Builder(size + map.size(), comparator)
                .putAll(this)
                .putAll(map)
                .build();
    }

    // -------- Builder --------

    /**
     * A builder for making unmodifiable sorted map.
     *
     * @param  The map key type.
     * @param  The map value type.
     */
    public final static class Builder
            extends UnmodifiableMapBuilder, Builder>
            implements MapBuilder {
        private Entry[]               array;
        private int                         size;
        private UnmodifiableSortedMap justBuilt;

        private final Comparator           comparator;
        private final Comparator> entryComparator;

        @SuppressWarnings("unchecked,rawtypes")
        Builder(int initialCapacity, Comparator comparator) {
            this.array = new Entry[initialCapacity];
            this.size = 0;
            this.comparator = comparator;
            this.entryComparator = makeEntryComparator(comparator);
            this.justBuilt = null;
        }

        @Override
        public Builder put(K key, V value) {
            ensureCapacity(size + 1);
            array[size++] = new AbstractMap.SimpleImmutableEntry<>(key, value);
            return this;
        }

        @Override
        @SuppressWarnings("unchecked,rawtypes")
        public Builder putAll(Map map) {
            if (map.isEmpty()) {
                return this;
            }
            ensureCapacity(size + map.size());
            if (map instanceof UnmodifiableMapBase) {
                UnmodifiableMapBase base = (UnmodifiableMapBase) map;
                for (int i = 0; i < base.size; ++i) {
                    array[size++] = (Entry) base.entries[i];
                }
            } else {
                for (Entry entry : map.entrySet()) {
                    array[size++] = new AbstractMap.SimpleImmutableEntry<>(entry.getKey(), entry.getValue());
                }
            }
            return this;
        }

        @Override
        public UnmodifiableSortedMap build() {
            if (size == 0 && comparator == null) {
                return sortedMapOf();
            }
            if (justBuilt != null) {
                return justBuilt;
            }
            makeSorted(1);
            justBuilt = new UnmodifiableSortedMap<>(size, array, comparator, entryComparator);
            return justBuilt;
        }

        @SuppressWarnings("unchecked")
        private void makeSorted(int minSize) {
            if (size == 0) {
                return;
            }

            // A: Sort
            Arrays.sort(array, 0, size, entryComparator);

            // B: Deduplicate
            final int originalSize = size;
            for (int i = 1; i < originalSize; ++i) {
                if (array[i].getKey().equals(array[i - 1].getKey())) {
                    // The last entry is kept.
                    array[i - 1] = null;
                    --size;
                }
            }

            // C: compact away null values.
            if (size < originalSize) {
                if (array.length - max(size, minSize) > 1024) {
                    // In order to save memory, minimize larger arrays.
                    @SuppressWarnings("rawtypes")
                    Entry[] compact = new Entry[max(minSize, size)];
                    int pos = 0;
                    for (int i = 0; i < originalSize; ++i) {
                        @SuppressWarnings("rawtypes")
                        Entry o = array[i];
                        if (o != null) {
                            compact[pos++] = o;
                        }
                    }
                    array = compact;
                } else {
                    for (int moveTo = 0, moveFrom = 1;
                         moveTo < size && moveFrom < originalSize;
                         ++moveTo, ++moveFrom) {
                        if (array[moveTo] == null) {
                            while (array[moveFrom] == null) {
                                ++moveFrom;
                            }
                            array[moveTo] = array[moveFrom];
                            array[moveFrom] = null;
                        }
                    }
                }
            }
        }

        @SuppressWarnings("unchecked")
        private void ensureCapacity(int newSize) {
            if (array.length < newSize) {
                @SuppressWarnings("rawtypes")
                Entry[] old = array;
                array = new Entry[old.length * 2];
                System.arraycopy(old, 0, array, 0, size);
                makeSorted(newSize);
            } else if (justBuilt != null) {
                @SuppressWarnings("rawtypes")
                Entry[] old = array;
                array = new Entry[old.length];
                System.arraycopy(old, 0, array, 0, size);
                // Already sorted.
            }
            justBuilt = null;
        }
    }

    // -------- UnmodifiableMapBase : Protected --------

    @Override
    protected Set> makeEntrySet() {
        if (size == 0) {
            return UnmodifiableSortedSet.sortedSetOf();
        }
        return new UnmodifiableSortedSet<>(0, size, entries, entryComparator);
    }


    @Override
    protected Set makeKeySet() {
        if (size == 0) {
            return UnmodifiableSortedSet.sortedSetOf();
        }
        Object[] keys = new Object[size];
        for (int i = 0; i < size; ++i) {
            keys[i] = entries[i].getKey();
        }
        return new UnmodifiableSortedSet<>(0, size, keys, comparator);
    }

    // -------- Private --------

    private UnmodifiableSortedMap(int size, Entry[] entries, Comparator comparator) {
        this(size, entries, comparator, makeEntryComparator(comparator));
    }

    UnmodifiableSortedMap(int size,
                          Entry[] entries,
                          Comparator comparator,
                          Comparator> entryComparator) {
        super(size, entries);
        this.comparator = comparator;
        this.entryComparator = entryComparator;
    }

    private Entry find(K key) {
        int index = findIndex(key);
        if (index >= 0) {
            return entries[index];
        }
        return null;
    }

    private int findIndex(K key) {
        int insertPos = Arrays.binarySearch(entries,
                                            0,
                                            size,
                                            new AbstractMap.SimpleImmutableEntry<>(key, null),
                                            entryComparator);
        int candiate = -1 - insertPos;
        if (candiate == size) {
            return insertPos;
        }
        if (entries[candiate].getKey().equals(key)) {
            return candiate;
        }
        return insertPos;
    }

    @SafeVarargs
    private static  UnmodifiableSortedMap construct(Entry... entries) {
        Comparator> entryComparator = makeEntryComparator(null);
        Arrays.sort(entries, entryComparator);
        return new UnmodifiableSortedMap<>(entries.length, entries, null, entryComparator);
    }

    static  Comparator> makeEntryComparator(Comparator comparator) {
        @SuppressWarnings("unchecked")
        Comparator> base = comparator == null ?
                                       Entry.comparingByKey((Comparator) Comparator.naturalOrder()) :
                                       Entry.comparingByKey(comparator);
        // This should make it sort null values before non-null.
        // This is used to get the correct binary search behavior based on null values in search key.
        return base.thenComparing(e -> e.getValue() != null);
    }

    @SuppressWarnings("unchecked,rawtypes")
    private static final UnmodifiableSortedMap EMPTY = new UnmodifiableSortedMap<>(
            0, NO_ENTRIES, null);

    private final transient Comparator   comparator;
    private final transient Comparator> entryComparator;

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy