1b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets/*
2bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette * Copyright 2018 The Android Open Source Project
3b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets *
4b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * Licensed under the Apache License, Version 2.0 (the "License");
5b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * you may not use this file except in compliance with the License.
6b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * You may obtain a copy of the License at
7b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets *
8b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets *      http://www.apache.org/licenses/LICENSE-2.0
9b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets *
10b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * Unless required by applicable law or agreed to in writing, software
11b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * distributed under the License is distributed on an "AS IS" BASIS,
12b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * See the License for the specific language governing permissions and
14b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * limitations under the License.
15b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets */
16b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets
17bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverettepackage androidx.arch.core.internal;
18b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets
19bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.annotation.NonNull;
20bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.annotation.RestrictTo;
21b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets
22b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinetsimport java.util.HashMap;
23b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinetsimport java.util.Map;
24b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets
25b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets/**
26b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * Poor's man LinkedHashMap, which supports modifications during iterations.
27b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * Takes more memory that {@link SafeIterableMap}
28b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * It is NOT thread safe.
29b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets *
30b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * @param <K> Key type
31b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * @param <V> Value type
32b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets * @hide
33b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets */
34b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
35b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinetspublic class FastSafeIterableMap<K, V> extends SafeIterableMap<K, V> {
36b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets
37b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    private HashMap<K, Entry<K, V>> mHashMap = new HashMap<>();
38b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets
39b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    @Override
40b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    protected Entry<K, V> get(K k) {
41b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets        return mHashMap.get(k);
42b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    }
43b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets
44b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    @Override
45b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    public V putIfAbsent(@NonNull K key, @NonNull V v) {
46b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets        Entry<K, V> current = get(key);
47b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets        if (current != null) {
48b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets            return current.mValue;
49b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets        }
50b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets        mHashMap.put(key, put(key, v));
51b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets        return null;
52b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    }
53b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets
5476c131bad1324a65e35a962f7cb1e8ac4da3ef5bSergey Vasilinets    @Override
5576c131bad1324a65e35a962f7cb1e8ac4da3ef5bSergey Vasilinets    public V remove(@NonNull K key) {
5676c131bad1324a65e35a962f7cb1e8ac4da3ef5bSergey Vasilinets        V removed = super.remove(key);
5776c131bad1324a65e35a962f7cb1e8ac4da3ef5bSergey Vasilinets        mHashMap.remove(key);
5876c131bad1324a65e35a962f7cb1e8ac4da3ef5bSergey Vasilinets        return removed;
5976c131bad1324a65e35a962f7cb1e8ac4da3ef5bSergey Vasilinets    }
6076c131bad1324a65e35a962f7cb1e8ac4da3ef5bSergey Vasilinets
61b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    /**
62b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets     * Returns {@code true} if this map contains a mapping for the specified
63b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets     * key.
64b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets     */
65b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    public boolean contains(K key) {
66b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets        return mHashMap.containsKey(key);
67b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    }
68b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets
69b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    /**
70b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets     * Return an entry added to prior to an entry associated with the given key.
71b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets     *
72b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets     * @param k the key
73b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets     */
74b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    public Map.Entry<K, V> ceil(K k) {
75b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets        if (contains(k)) {
76b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets            return mHashMap.get(k).mPrevious;
77b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets        }
78b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets        return null;
79b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets    }
80b546e977676e83f932e88e6c6d4e6e2710621bc9Sergey Vasilinets}
81