001/*
002 * Copyright 2018 Paul Schaub.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.pgpainless.util;
017
018import javax.annotation.Nonnull;
019import java.util.Collection;
020import java.util.HashMap;
021import java.util.HashSet;
022import java.util.Map;
023import java.util.Set;
024
025public class MultiMap<K, V> {
026
027    private final Map<K, Set<V>> map;
028
029    public MultiMap() {
030        map = new HashMap<>();
031    }
032
033    public MultiMap(@Nonnull MultiMap<K, V> other) {
034        this.map = new HashMap<>();
035        for (K k : other.map.keySet()) {
036            map.put(k, new HashSet<>(other.map.get(k)));
037        }
038    }
039
040    public MultiMap(@Nonnull Map<K, Set<V>> content) {
041        this.map = new HashMap<>(content);
042    }
043
044    public int size() {
045        return map.size();
046    }
047
048    public boolean isEmpty() {
049        return map.isEmpty();
050    }
051
052    public boolean containsKey(K o) {
053        return map.containsKey(o);
054    }
055
056    public boolean containsValue(V o) {
057        for (Set<V> values : map.values()) {
058            if (values.contains(o)) return true;
059        }
060        return false;
061    }
062
063    public Set<V> get(K o) {
064        return map.get(o);
065    }
066
067    public void put(K k, V v) {
068        Set<V> values = map.get(k);
069        if (values == null) {
070            values = new HashSet<>();
071            map.put(k, values);
072        }
073        values.add(v);
074    }
075
076    public void put(K k, Set<V> vs) {
077        for (V v : vs) {
078            put(k, v);
079        }
080    }
081
082    public void remove(K o) {
083        for (Set<V> values : map.values()) {
084            values.remove(o);
085        }
086    }
087
088    public void putAll(Map<? extends K, ? extends Set<V>> _map) {
089        for (K key : _map.keySet()) {
090            Set<V> vs = this.map.get(key);
091            if (vs == null) {
092                vs = new HashSet<>();
093                this.map.put(key, vs);
094            }
095            vs.addAll(_map.get(key));
096        }
097    }
098
099    public void clear() {
100        map.clear();
101    }
102
103    public Set<K> keySet() {
104        return map.keySet();
105    }
106
107    public Collection<Set<V>> values() {
108        return map.values();
109    }
110
111    public Set<Map.Entry<K, Set<V>>> entrySet() {
112        return map.entrySet();
113    }
114
115    @Override
116    public boolean equals(Object o) {
117        if (o == null) {
118            return false;
119        }
120
121        if (!(o instanceof MultiMap)) {
122            return false;
123        }
124
125        if (this == o) {
126            return true;
127        }
128
129        return map.equals(((MultiMap) o).map);
130    }
131
132    @Override
133    public int hashCode() {
134        return map.hashCode();
135    }
136}