Path: blob/v3_openjdk/jre_lwjgl3glfw/src/main/java/android/util/MapCollections.java
2129 views
/*1* Copyright (C) 2013 The Android Open Source Project2*3* Licensed under the Apache License, Version 2.0 (the "License");4* you may not use this file except in compliance with the License.5* You may obtain a copy of the License at6*7* http://www.apache.org/licenses/LICENSE-2.08*9* Unless required by applicable law or agreed to in writing, software10* distributed under the License is distributed on an "AS IS" BASIS,11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12* See the License for the specific language governing permissions and13* limitations under the License.14*/1516package android.util;1718import java.lang.reflect.Array;19import java.util.Collection;20import java.util.Iterator;21import java.util.Map;22import java.util.Set;2324/**25* Helper for writing standard Java collection interfaces to a data26* structure like {@link ArrayMap}.27* @hide28*/29abstract class MapCollections<K, V> {30EntrySet mEntrySet;31KeySet mKeySet;32ValuesCollection mValues;3334final class ArrayIterator<T> implements Iterator<T> {35final int mOffset;36int mSize;37int mIndex;38boolean mCanRemove = false;3940ArrayIterator(int offset) {41mOffset = offset;42mSize = colGetSize();43}4445@Override46public boolean hasNext() {47return mIndex < mSize;48}4950@Override51public T next() {52Object res = colGetEntry(mIndex, mOffset);53mIndex++;54mCanRemove = true;55return (T)res;56}5758@Override59public void remove() {60if (!mCanRemove) {61throw new IllegalStateException();62}63mIndex--;64mSize--;65mCanRemove = false;66colRemoveAt(mIndex);67}68}6970final class MapIterator implements Iterator<Map.Entry<K, V>>, Map.Entry<K, V> {71int mEnd;72int mIndex;73boolean mEntryValid = false;7475MapIterator() {76mEnd = colGetSize() - 1;77mIndex = -1;78}7980@Override81public boolean hasNext() {82return mIndex < mEnd;83}8485@Override86public Map.Entry<K, V> next() {87mIndex++;88mEntryValid = true;89return this;90}9192@Override93public void remove() {94if (!mEntryValid) {95throw new IllegalStateException();96}97colRemoveAt(mIndex);98mIndex--;99mEnd--;100mEntryValid = false;101}102103@Override104public K getKey() {105if (!mEntryValid) {106throw new IllegalStateException(107"This container does not support retaining Map.Entry objects");108}109return (K)colGetEntry(mIndex, 0);110}111112@Override113public V getValue() {114if (!mEntryValid) {115throw new IllegalStateException(116"This container does not support retaining Map.Entry objects");117}118return (V)colGetEntry(mIndex, 1);119}120121@Override122public V setValue(V object) {123if (!mEntryValid) {124throw new IllegalStateException(125"This container does not support retaining Map.Entry objects");126}127return colSetValue(mIndex, object);128}129130@Override131public final boolean equals(Object o) {132if (!mEntryValid) {133throw new IllegalStateException(134"This container does not support retaining Map.Entry objects");135}136if (!(o instanceof Map.Entry)) {137return false;138}139Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;140return Objects.equal(e.getKey(), colGetEntry(mIndex, 0))141&& Objects.equal(e.getValue(), colGetEntry(mIndex, 1));142}143144@Override145public final int hashCode() {146if (!mEntryValid) {147throw new IllegalStateException(148"This container does not support retaining Map.Entry objects");149}150final Object key = colGetEntry(mIndex, 0);151final Object value = colGetEntry(mIndex, 1);152return (key == null ? 0 : key.hashCode()) ^153(value == null ? 0 : value.hashCode());154}155156@Override157public final String toString() {158return getKey() + "=" + getValue();159}160}161162final class EntrySet implements Set<Map.Entry<K, V>> {163@Override164public boolean add(Map.Entry<K, V> object) {165throw new UnsupportedOperationException();166}167168@Override169public boolean addAll(Collection<? extends Map.Entry<K, V>> collection) {170int oldSize = colGetSize();171for (Map.Entry<K, V> entry : collection) {172colPut(entry.getKey(), entry.getValue());173}174return oldSize != colGetSize();175}176177@Override178public void clear() {179colClear();180}181182@Override183public boolean contains(Object o) {184if (!(o instanceof Map.Entry))185return false;186Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;187int index = colIndexOfKey(e.getKey());188if (index < 0) {189return false;190}191Object foundVal = colGetEntry(index, 1);192return Objects.equal(foundVal, e.getValue());193}194195@Override196public boolean containsAll(Collection<?> collection) {197Iterator<?> it = collection.iterator();198while (it.hasNext()) {199if (!contains(it.next())) {200return false;201}202}203return true;204}205206@Override207public boolean isEmpty() {208return colGetSize() == 0;209}210211@Override212public Iterator<Map.Entry<K, V>> iterator() {213return new MapIterator();214}215216@Override217public boolean remove(Object object) {218throw new UnsupportedOperationException();219}220221@Override222public boolean removeAll(Collection<?> collection) {223throw new UnsupportedOperationException();224}225226@Override227public boolean retainAll(Collection<?> collection) {228throw new UnsupportedOperationException();229}230231@Override232public int size() {233return colGetSize();234}235236@Override237public Object[] toArray() {238throw new UnsupportedOperationException();239}240241@Override242public <T> T[] toArray(T[] array) {243throw new UnsupportedOperationException();244}245246@Override247public boolean equals(Object object) {248return equalsSetHelper(this, object);249}250251@Override252public int hashCode() {253int result = 0;254for (int i=colGetSize()-1; i>=0; i--) {255final Object key = colGetEntry(i, 0);256final Object value = colGetEntry(i, 1);257result += ( (key == null ? 0 : key.hashCode()) ^258(value == null ? 0 : value.hashCode()) );259}260return result;261}262};263264final class KeySet implements Set<K> {265266@Override267public boolean add(K object) {268throw new UnsupportedOperationException();269}270271@Override272public boolean addAll(Collection<? extends K> collection) {273throw new UnsupportedOperationException();274}275276@Override277public void clear() {278colClear();279}280281@Override282public boolean contains(Object object) {283return colIndexOfKey(object) >= 0;284}285286@Override287public boolean containsAll(Collection<?> collection) {288return containsAllHelper(colGetMap(), collection);289}290291@Override292public boolean isEmpty() {293return colGetSize() == 0;294}295296@Override297public Iterator<K> iterator() {298return new ArrayIterator<K>(0);299}300301@Override302public boolean remove(Object object) {303int index = colIndexOfKey(object);304if (index >= 0) {305colRemoveAt(index);306return true;307}308return false;309}310311@Override312public boolean removeAll(Collection<?> collection) {313return removeAllHelper(colGetMap(), collection);314}315316@Override317public boolean retainAll(Collection<?> collection) {318return retainAllHelper(colGetMap(), collection);319}320321@Override322public int size() {323return colGetSize();324}325326@Override327public Object[] toArray() {328return toArrayHelper(0);329}330331@Override332public <T> T[] toArray(T[] array) {333return toArrayHelper(array, 0);334}335336@Override337public boolean equals(Object object) {338return equalsSetHelper(this, object);339}340341@Override342public int hashCode() {343int result = 0;344for (int i=colGetSize()-1; i>=0; i--) {345Object obj = colGetEntry(i, 0);346result += obj == null ? 0 : obj.hashCode();347}348return result;349}350};351352final class ValuesCollection implements Collection<V> {353354@Override355public boolean add(V object) {356throw new UnsupportedOperationException();357}358359@Override360public boolean addAll(Collection<? extends V> collection) {361throw new UnsupportedOperationException();362}363364@Override365public void clear() {366colClear();367}368369@Override370public boolean contains(Object object) {371return colIndexOfValue(object) >= 0;372}373374@Override375public boolean containsAll(Collection<?> collection) {376Iterator<?> it = collection.iterator();377while (it.hasNext()) {378if (!contains(it.next())) {379return false;380}381}382return true;383}384385@Override386public boolean isEmpty() {387return colGetSize() == 0;388}389390@Override391public Iterator<V> iterator() {392return new ArrayIterator<V>(1);393}394395@Override396public boolean remove(Object object) {397int index = colIndexOfValue(object);398if (index >= 0) {399colRemoveAt(index);400return true;401}402return false;403}404405@Override406public boolean removeAll(Collection<?> collection) {407int N = colGetSize();408boolean changed = false;409for (int i=0; i<N; i++) {410Object cur = colGetEntry(i, 1);411if (collection.contains(cur)) {412colRemoveAt(i);413i--;414N--;415changed = true;416}417}418return changed;419}420421@Override422public boolean retainAll(Collection<?> collection) {423int N = colGetSize();424boolean changed = false;425for (int i=0; i<N; i++) {426Object cur = colGetEntry(i, 1);427if (!collection.contains(cur)) {428colRemoveAt(i);429i--;430N--;431changed = true;432}433}434return changed;435}436437@Override438public int size() {439return colGetSize();440}441442@Override443public Object[] toArray() {444return toArrayHelper(1);445}446447@Override448public <T> T[] toArray(T[] array) {449return toArrayHelper(array, 1);450}451};452453public static <K, V> boolean containsAllHelper(Map<K, V> map, Collection<?> collection) {454Iterator<?> it = collection.iterator();455while (it.hasNext()) {456if (!map.containsKey(it.next())) {457return false;458}459}460return true;461}462463public static <K, V> boolean removeAllHelper(Map<K, V> map, Collection<?> collection) {464int oldSize = map.size();465Iterator<?> it = collection.iterator();466while (it.hasNext()) {467map.remove(it.next());468}469return oldSize != map.size();470}471472public static <K, V> boolean retainAllHelper(Map<K, V> map, Collection<?> collection) {473int oldSize = map.size();474Iterator<K> it = map.keySet().iterator();475while (it.hasNext()) {476if (!collection.contains(it.next())) {477it.remove();478}479}480return oldSize != map.size();481}482483public Object[] toArrayHelper(int offset) {484final int N = colGetSize();485Object[] result = new Object[N];486for (int i=0; i<N; i++) {487result[i] = colGetEntry(i, offset);488}489return result;490}491492public <T> T[] toArrayHelper(T[] array, int offset) {493final int N = colGetSize();494if (array.length < N) {495@SuppressWarnings("unchecked") T[] newArray496= (T[]) Array.newInstance(array.getClass().getComponentType(), N);497array = newArray;498}499for (int i=0; i<N; i++) {500array[i] = (T)colGetEntry(i, offset);501}502if (array.length > N) {503array[N] = null;504}505return array;506}507508public static <T> boolean equalsSetHelper(Set<T> set, Object object) {509if (set == object) {510return true;511}512if (object instanceof Set) {513Set<?> s = (Set<?>) object;514515try {516return set.size() == s.size() && set.containsAll(s);517} catch (NullPointerException ignored) {518return false;519} catch (ClassCastException ignored) {520return false;521}522}523return false;524}525526public Set<Map.Entry<K, V>> getEntrySet() {527if (mEntrySet == null) {528mEntrySet = new EntrySet();529}530return mEntrySet;531}532533public Set<K> getKeySet() {534if (mKeySet == null) {535mKeySet = new KeySet();536}537return mKeySet;538}539540public Collection<V> getValues() {541if (mValues == null) {542mValues = new ValuesCollection();543}544return mValues;545}546547protected abstract int colGetSize();548protected abstract Object colGetEntry(int index, int offset);549protected abstract int colIndexOfKey(Object key);550protected abstract int colIndexOfValue(Object key);551protected abstract Map<K, V> colGetMap();552protected abstract void colPut(K key, V value);553protected abstract V colSetValue(int index, V value);554protected abstract void colRemoveAt(int index);555protected abstract void colClear();556}557558559