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

com.github.protobufel.multikeymap.LiteSetMultimap Maven / Gradle / Ivy

Go to download

Java 8 implementation of the multi-key map. It behaves like a regular generic Map with the additional ability of getting its values by any combination of partial keys.

The newest version!
/*
 *    Copyright 2017 David Tesler
 *
 *    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 com.github.protobufel.multikeymap;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A lite wrapper of a mutable Map which values are Set of actual values
 *
 * @param  the type of Map's key
 * @param  the type of actual values
 * @author David Tesler
 */
interface LiteSetMultimap {

    /**
     * Creates a new default instance of LiteSetMultimap.
     *
     * @return a new instance of the LiteSetMultimap's default implementation.
     */
    static  LiteSetMultimap newInstance() {
        return newInstance(false);
    }

    /**
     * Creates a new instance of LiteSetMultimap based on the provided empty map.
     *
     * @param concurrent create a concurrent instance if true, un-synchronized, regular instance, otherwise
     * @return a new instance of LiteSetMultimap based on the provided empty map
     */
    static  LiteSetMultimap newInstance(boolean concurrent) {
        return concurrent ? new ConcurrentLiteSetMultimap<>() : new RegularLiteSetMultimap<>();
    }

    /**
     * Clears all data
     */
    void clear();

    /**
     * Finds the record with the specified key and removes the value, if present, from the set of its
     * values. If there are no values left in the set, removes the entire record from the
     * LiteSetMultimap.
     *
     * @param key   the key to search for
     * @param value the value to be removed corresponding to the search key
     * @return true if value is removed, false, otherwise
     */
    boolean remove(K key, V value);

    /**
     * Gets the number of records in the LiteSetMultimap.
     *
     * @return the size of the the LiteSetMultimap, zero if empty
     */
    int size();

    /**
     * Tells whether the LiteSetMultimap is empty.
     *
     * @return true if the LiteSetMultimap is empty, false, otherwise
     */
    boolean isEmpty();

    /**
     * Gets the live Set of the values corresponding to the search key.
     *
     * @param key the key to search for
     * @return the Set of the values corresponding to the search key
     */
    Set get(K key);

    /**
     * Adds the value to the set of values corresponding to the search key. If no such record is
     * found, creates a new record with the set initialized to the value.
     *
     * @param key   the key to search for
     * @param value the value to add to the set of values corresponding to the search key
     * @return true if value is added, false, otherwise
     */
    boolean put(K key, V value);

    /**
     * Returns whether this class supports concurrent access.
     */
    default boolean isConcurrent() {
        return getClass().isAssignableFrom(ConcurrentLiteSetMultimap.class);
    }

    class ConcurrentLiteSetMultimap extends BaseLiteSetMultimap implements Serializable {
        private static final long serialVersionUID = -5018582265479564955L;

        public ConcurrentLiteSetMultimap() {
            super(new ConcurrentHashMap<>());
        }

        @Override
        protected Set newSet() {
            return new ConcurrentHashMap().keySet(true);
        }
    }

    class RegularLiteSetMultimap extends BaseLiteSetMultimap implements Serializable {
        private static final long serialVersionUID = -1557045174464645635L;

        public RegularLiteSetMultimap() {
            super(new HashMap<>());
        }

        @Override
        protected Set newSet() {
            return new HashSet<>();
        }
    }

    abstract class BaseLiteSetMultimap implements LiteSetMultimap {
        /**
         * The base map this class is wrapping
         *
         * @serial
         */
        private final Map> map;

        public BaseLiteSetMultimap(Map> map) {
            this.map = map;
        }

        abstract Set newSet();

        @Override
        public int size() {
            return map.size();
        }

        @Override
        public boolean isEmpty() {
            return map.isEmpty();
        }

        @Override
        public Set get(final Object key) {
            return map.get(key);
        }

        @Override
        public boolean put(final K key, final V value) {
            return map.computeIfAbsent(Objects.requireNonNull(key), k -> newSet())
                    .add(Objects.requireNonNull(value));
        }

        @Override
        public void clear() {
            map.clear();
        }

        @Override
        public boolean remove(final K key, final V value) {
            final boolean[] removed = {false};
            map.computeIfPresent(Objects.requireNonNull(key), (k, v) -> {
                if ((removed[0] = v.remove(value)) && v.isEmpty()) {
                    return null;
                }

                return v;
            });

            return removed[0];
        }

        @Override
        public boolean equals(final Object o) {
            if (o == this) {
                return true;
            }

            if (!(o instanceof Map)) {
                return false;
            }

            return map.equals(o);
        }

        @Override
        public int hashCode() {
            return map.hashCode();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy