blob: 3ec6b810fda83b1d597e4a2b7ab7a60ad62c10bf [file] [log] [blame]
Kweku Adamsa26ae902019-11-14 14:59:57 -08001/*
2 * Copyright (C) 2019 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
17package android.util;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.annotation.TestApi;
22
23import java.util.function.Consumer;
24
25/**
26 * A sparse array of ArrayMaps, which is suitable for holding (userId, packageName)->object
27 * associations.
28 *
29 * @param <T> Any class
30 * @hide
31 */
32@TestApi
33public class SparseArrayMap<T> {
34 private final SparseArray<ArrayMap<String, T>> mData = new SparseArray<>();
35
36 /** Add an entry associating obj with the int-String pair. */
37 public void add(int key, @NonNull String mapKey, @Nullable T obj) {
38 ArrayMap<String, T> data = mData.get(key);
39 if (data == null) {
40 data = new ArrayMap<>();
41 mData.put(key, data);
42 }
43 data.put(mapKey, obj);
44 }
45
46 /** Remove all entries from the map. */
47 public void clear() {
48 for (int i = 0; i < mData.size(); ++i) {
49 mData.valueAt(i).clear();
50 }
51 }
52
53 /** Return true if the structure contains an explicit entry for the int-String pair. */
54 public boolean contains(int key, @NonNull String mapKey) {
55 return mData.contains(key) && mData.get(key).containsKey(mapKey);
56 }
57
58 /** Removes all the data for the key, if there was any. */
59 public void delete(int key) {
60 mData.delete(key);
61 }
62
63 /**
64 * Removes the data for the key and mapKey, if there was any.
65 *
66 * @return Returns the value that was stored under the keys, or null if there was none.
67 */
68 @Nullable
69 public T delete(int key, @NonNull String mapKey) {
70 ArrayMap<String, T> data = mData.get(key);
71 if (data != null) {
72 return data.remove(mapKey);
73 }
74 return null;
75 }
76
77 /**
78 * Get the value associated with the int-String pair.
79 */
80 @Nullable
81 public T get(int key, @NonNull String mapKey) {
82 ArrayMap<String, T> data = mData.get(key);
83 if (data != null) {
84 return data.get(mapKey);
85 }
86 return null;
87 }
88
89 /**
90 * Returns the value to which the specified key and mapKey are mapped, or defaultValue if this
91 * map contains no mapping for them.
92 */
93 @Nullable
94 public T getOrDefault(int key, @NonNull String mapKey, T defaultValue) {
95 if (mData.contains(key)) {
96 ArrayMap<String, T> data = mData.get(key);
97 if (data != null && data.containsKey(mapKey)) {
98 return data.get(mapKey);
99 }
100 }
101 return defaultValue;
102 }
103
104 /** @see SparseArray#indexOfKey */
105 public int indexOfKey(int key) {
106 return mData.indexOfKey(key);
107 }
108
109 /**
110 * Returns the index of the mapKey.
111 *
112 * @see SparseArray#indexOfKey
113 */
114 public int indexOfKey(int key, @NonNull String mapKey) {
115 ArrayMap<String, T> data = mData.get(key);
116 if (data != null) {
117 return data.indexOfKey(mapKey);
118 }
119 return -1;
120 }
121
122 /** Returns the key at the given index. */
123 public int keyAt(int index) {
124 return mData.keyAt(index);
125 }
126
127 /** Returns the map's key at the given mapIndex for the given keyIndex. */
128 @NonNull
129 public String keyAt(int keyIndex, int mapIndex) {
130 return mData.valueAt(keyIndex).keyAt(mapIndex);
131 }
132
133 /** Returns the size of the outer array. */
134 public int numMaps() {
135 return mData.size();
136 }
137
138 /** Returns the number of elements in the map of the given key. */
139 public int numElementsForKey(int key) {
140 ArrayMap<String, T> data = mData.get(key);
141 return data == null ? 0 : data.size();
142 }
143
144 /** Returns the value T at the given key and map index. */
145 @Nullable
146 public T valueAt(int keyIndex, int mapIndex) {
147 return mData.valueAt(keyIndex).valueAt(mapIndex);
148 }
149
150 /** Iterate through all int-String pairs and operate on all of the values. */
151 public void forEach(@NonNull Consumer<T> consumer) {
152 for (int i = numMaps() - 1; i >= 0; --i) {
153 ArrayMap<String, T> data = mData.valueAt(i);
154 for (int j = data.size() - 1; j >= 0; --j) {
155 consumer.accept(data.valueAt(j));
156 }
157 }
158 }
159}