1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.util;
18 
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.Map;
23 import java.util.Set;
24 
25 /**
26  * A simple implementation of a multimap that maps keys to sets of values.
27  *
28  * This class is (and should remain) drop-in replaceable with Guava's SetMultimap.
29  *
30  * @param <K> The type of the keys in the map.
31  * @param <V> The type of the values in the map.
32  */
33 public class SetMultimap<K, V> {
34     private Map<K, Set<V>> mMap;
35 
36     /** Creates a new {@link #SetMultimap}. */
SetMultimap()37     public SetMultimap() {
38         mMap = new HashMap<>();
39     }
40 
41     /** Gets the set of values associated with a given key. */
get(K key)42     public Set<V> get(K key) {
43         return Collections.unmodifiableSet(mMap.getOrDefault(key, Collections.emptySet()));
44     }
45 
46     /** Adds a value to the set associated with a key. */
put(K key, V value)47     public boolean put(K key, V value) {
48         return mMap.computeIfAbsent(key, k -> new HashSet<>()).add(value);
49     }
50 
51     /** Checks if the multimap contains the given key and value. */
containsEntry(K key, V value)52     public boolean containsEntry(K key, V value) {
53         Set<V> set = mMap.get(key);
54         return set != null && set.contains(value);
55     }
56 
57     /** Removes the given value from the set of the given key. */
remove(K key, V value)58     public boolean remove(K key, V value) {
59         Set<V> set = mMap.get(key);
60         if (set == null) {
61             return false;
62         }
63 
64         boolean removed = set.remove(value);
65         if (set.isEmpty()) {
66             mMap.remove(key);
67         }
68         return removed;
69     }
70 
71     /** Clears all entries in the map. */
clear()72     public void clear() {
73         mMap.clear();
74     }
75 
76     /** Gets the set of keys stored in the map. */
keySet()77     public Set<K> keySet() {
78         return Collections.unmodifiableSet(mMap.keySet());
79     }
80 }
81