diff options
-rw-r--r-- | api/current.txt | 28 | ||||
-rw-r--r-- | core/java/android/app/Activity.java | 51 | ||||
-rw-r--r-- | core/java/android/app/AppOpsManager.java | 7 | ||||
-rw-r--r-- | core/java/android/app/Fragment.java | 6 | ||||
-rw-r--r-- | core/java/android/util/ArrayMap.java | 20 | ||||
-rw-r--r-- | core/java/android/util/ArraySet.java | 18 | ||||
-rw-r--r-- | core/java/android/util/ContainerHelpers.java | 63 | ||||
-rw-r--r-- | core/java/android/util/LongSparseArray.java | 59 | ||||
-rw-r--r-- | core/java/android/util/LongSparseLongArray.java | 39 | ||||
-rw-r--r-- | core/java/android/util/SparseArray.java | 70 | ||||
-rw-r--r-- | core/java/android/util/SparseBooleanArray.java | 43 | ||||
-rw-r--r-- | core/java/android/util/SparseIntArray.java | 39 | ||||
-rw-r--r-- | core/java/android/util/SparseLongArray.java | 41 |
13 files changed, 358 insertions, 126 deletions
diff --git a/api/current.txt b/api/current.txt index e0025ea..9073348 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24794,6 +24794,33 @@ package android.util { ctor public AndroidRuntimeException(java.lang.Exception); } + public final class ArrayMap implements java.util.Map { + ctor public ArrayMap(); + ctor public ArrayMap(int); + ctor public ArrayMap(android.util.ArrayMap); + method public void clear(); + method public boolean containsAll(java.util.Collection<?>); + method public boolean containsKey(java.lang.Object); + method public boolean containsValue(java.lang.Object); + method public void ensureCapacity(int); + method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public V get(java.lang.Object); + method public boolean isEmpty(); + method public K keyAt(int); + method public java.util.Set<K> keySet(); + method public V put(K, V); + method public void putAll(android.util.ArrayMap<? extends K, ? extends V>); + method public void putAll(java.util.Map<? extends K, ? extends V>); + method public V remove(java.lang.Object); + method public boolean removeAll(java.util.Collection<?>); + method public V removeAt(int); + method public boolean retainAll(java.util.Collection<?>); + method public V setValueAt(int, V); + method public int size(); + method public V valueAt(int); + method public java.util.Collection<V> values(); + } + public class AtomicFile { ctor public AtomicFile(java.io.File); method public void delete(); @@ -25147,6 +25174,7 @@ package android.util { method public void put(int, E); method public void remove(int); method public void removeAt(int); + method public void removeAtRange(int, int); method public void setValueAt(int, E); method public int size(); method public E valueAt(int); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index fa746ba..8f2f9ca 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -16,6 +16,7 @@ package android.app; +import android.util.ArrayMap; import com.android.internal.app.ActionBarImpl; import com.android.internal.policy.PolicyManager; @@ -700,7 +701,7 @@ public class Activity extends ContextThemeWrapper Object activity; HashMap<String, Object> children; ArrayList<Fragment> fragments; - HashMap<String, LoaderManagerImpl> loaders; + ArrayMap<String, LoaderManagerImpl> loaders; } /* package */ NonConfigurationInstances mLastNonConfigurationInstances; @@ -725,7 +726,7 @@ public class Activity extends ContextThemeWrapper } }; - HashMap<String, LoaderManagerImpl> mAllLoaderManagers; + ArrayMap<String, LoaderManagerImpl> mAllLoaderManagers; LoaderManagerImpl mLoaderManager; private static final class ManagedCursor { @@ -819,13 +820,13 @@ public class Activity extends ContextThemeWrapper return mLoaderManager; } mCheckedForLoaderManager = true; - mLoaderManager = getLoaderManager(null, mLoadersStarted, true); + mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true); return mLoaderManager; } LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) { if (mAllLoaderManagers == null) { - mAllLoaderManagers = new HashMap<String, LoaderManagerImpl>(); + mAllLoaderManagers = new ArrayMap<String, LoaderManagerImpl>(); } LoaderManagerImpl lm = mAllLoaderManagers.get(who); if (lm == null) { @@ -1036,7 +1037,7 @@ public class Activity extends ContextThemeWrapper if (mLoaderManager != null) { mLoaderManager.doStart(); } else if (!mCheckedForLoaderManager) { - mLoaderManager = getLoaderManager(null, mLoadersStarted, false); + mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false); } mCheckedForLoaderManager = true; } @@ -1648,17 +1649,18 @@ public class Activity extends ContextThemeWrapper if (mAllLoaderManagers != null) { // prune out any loader managers that were already stopped and so // have nothing useful to retain. - LoaderManagerImpl loaders[] = new LoaderManagerImpl[mAllLoaderManagers.size()]; - mAllLoaderManagers.values().toArray(loaders); - if (loaders != null) { - for (int i=0; i<loaders.length; i++) { - LoaderManagerImpl lm = loaders[i]; - if (lm.mRetaining) { - retainLoaders = true; - } else { - lm.doDestroy(); - mAllLoaderManagers.remove(lm.mWho); - } + final int N = mAllLoaderManagers.size(); + LoaderManagerImpl loaders[] = new LoaderManagerImpl[N]; + for (int i=N-1; i>=0; i--) { + loaders[i] = mAllLoaderManagers.valueAt(i); + } + for (int i=0; i<N; i++) { + LoaderManagerImpl lm = loaders[i]; + if (lm.mRetaining) { + retainLoaders = true; + } else { + lm.doDestroy(); + mAllLoaderManagers.remove(lm.mWho); } } } @@ -5236,14 +5238,15 @@ public class Activity extends ContextThemeWrapper } mFragments.dispatchStart(); if (mAllLoaderManagers != null) { - LoaderManagerImpl loaders[] = new LoaderManagerImpl[mAllLoaderManagers.size()]; - mAllLoaderManagers.values().toArray(loaders); - if (loaders != null) { - for (int i=0; i<loaders.length; i++) { - LoaderManagerImpl lm = loaders[i]; - lm.finishRetain(); - lm.doReportStart(); - } + final int N = mAllLoaderManagers.size(); + LoaderManagerImpl loaders[] = new LoaderManagerImpl[N]; + for (int i=N-1; i>=0; i--) { + loaders[i] = mAllLoaderManagers.valueAt(i); + } + for (int i=0; i<N; i++) { + LoaderManagerImpl lm = loaders[i]; + lm.finishRetain(); + lm.doReportStart(); } } } diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index de94bb7..c22de0c 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -16,12 +16,11 @@ package android.app; -import android.Manifest; +import android.util.ArrayMap; import com.android.internal.app.IAppOpsService; import com.android.internal.app.IAppOpsCallback; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import android.content.Context; @@ -53,8 +52,8 @@ import android.os.RemoteException; public class AppOpsManager { final Context mContext; final IAppOpsService mService; - final HashMap<Callback, IAppOpsCallback> mModeWatchers - = new HashMap<Callback, IAppOpsCallback>(); + final ArrayMap<Callback, IAppOpsCallback> mModeWatchers + = new ArrayMap<Callback, IAppOpsCallback>(); public static final int MODE_ALLOWED = 0; public static final int MODE_IGNORED = 1; diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index b6aeb84..6933a7a 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -26,6 +26,7 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.AndroidRuntimeException; +import android.util.ArrayMap; import android.util.AttributeSet; import android.util.DebugUtils; import android.util.Log; @@ -43,7 +44,6 @@ import android.widget.AdapterView; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.HashMap; final class FragmentState implements Parcelable { final String mClassName; @@ -342,8 +342,8 @@ final class FragmentState implements Parcelable { * the activity UI was in. */ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener { - private static final HashMap<String, Class<?>> sClassMap = - new HashMap<String, Class<?>>(); + private static final ArrayMap<String, Class<?>> sClassMap = + new ArrayMap<String, Class<?>>(); static final int INVALID_STATE = -1; // Invalid state used as a null value. static final int INITIALIZING = 0; // Not yet created. diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java index 18534c6..b80a14b 100644 --- a/core/java/android/util/ArrayMap.java +++ b/core/java/android/util/ArrayMap.java @@ -44,8 +44,6 @@ import java.util.Set; * you have no control over this shrinking -- if you set a capacity and then remove an * item, it may reduce the capacity to better match the current size. In the future an * explicit call to set the capacity should turn off this aggressive shrinking behavior.</p> - * - * @hide */ public final class ArrayMap<K, V> implements Map<K, V> { private static final boolean DEBUG = false; @@ -86,7 +84,7 @@ public final class ArrayMap<K, V> implements Map<K, V> { return ~0; } - int index = SparseArray.binarySearch(mHashes, N, hash); + int index = ContainerHelpers.binarySearch(mHashes, N, hash); // If the hash code wasn't found, then we have no entry for this key. if (index < 0) { @@ -188,8 +186,8 @@ public final class ArrayMap<K, V> implements Map<K, V> { * will grow once items are added to it. */ public ArrayMap() { - mHashes = SparseArray.EMPTY_INTS; - mArray = SparseArray.EMPTY_OBJECTS; + mHashes = ContainerHelpers.EMPTY_INTS; + mArray = ContainerHelpers.EMPTY_OBJECTS; mSize = 0; } @@ -198,8 +196,8 @@ public final class ArrayMap<K, V> implements Map<K, V> { */ public ArrayMap(int capacity) { if (capacity == 0) { - mHashes = SparseArray.EMPTY_INTS; - mArray = SparseArray.EMPTY_OBJECTS; + mHashes = ContainerHelpers.EMPTY_INTS; + mArray = ContainerHelpers.EMPTY_OBJECTS; } else { allocArrays(capacity); } @@ -223,8 +221,8 @@ public final class ArrayMap<K, V> implements Map<K, V> { public void clear() { if (mSize != 0) { freeArrays(mHashes, mArray, mSize); - mHashes = SparseArray.EMPTY_INTS; - mArray = SparseArray.EMPTY_OBJECTS; + mHashes = ContainerHelpers.EMPTY_INTS; + mArray = ContainerHelpers.EMPTY_OBJECTS; mSize = 0; } } @@ -439,8 +437,8 @@ public final class ArrayMap<K, V> implements Map<K, V> { // Now empty. if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0"); freeArrays(mHashes, mArray, mSize); - mHashes = SparseArray.EMPTY_INTS; - mArray = SparseArray.EMPTY_OBJECTS; + mHashes = ContainerHelpers.EMPTY_INTS; + mArray = ContainerHelpers.EMPTY_OBJECTS; mSize = 0; } else { if (mHashes.length > (BASE_SIZE*2) && mSize < mHashes.length/3) { diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java index 4e1d32c..1648ec9 100644 --- a/core/java/android/util/ArraySet.java +++ b/core/java/android/util/ArraySet.java @@ -85,7 +85,7 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { return ~0; } - int index = SparseArray.binarySearch(mHashes, N, hash); + int index = ContainerHelpers.binarySearch(mHashes, N, hash); // If the hash code wasn't found, then we have no entry for this key. if (index < 0) { @@ -187,8 +187,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { * will grow once items are added to it. */ public ArraySet() { - mHashes = SparseArray.EMPTY_INTS; - mArray = SparseArray.EMPTY_OBJECTS; + mHashes = ContainerHelpers.EMPTY_INTS; + mArray = ContainerHelpers.EMPTY_OBJECTS; mSize = 0; } @@ -197,8 +197,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { */ public ArraySet(int capacity) { if (capacity == 0) { - mHashes = SparseArray.EMPTY_INTS; - mArray = SparseArray.EMPTY_OBJECTS; + mHashes = ContainerHelpers.EMPTY_INTS; + mArray = ContainerHelpers.EMPTY_OBJECTS; } else { allocArrays(capacity); } @@ -223,8 +223,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { public void clear() { if (mSize != 0) { freeArrays(mHashes, mArray, mSize); - mHashes = SparseArray.EMPTY_INTS; - mArray = SparseArray.EMPTY_OBJECTS; + mHashes = ContainerHelpers.EMPTY_INTS; + mArray = ContainerHelpers.EMPTY_OBJECTS; mSize = 0; } } @@ -371,8 +371,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { // Now empty. if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0"); freeArrays(mHashes, mArray, mSize); - mHashes = SparseArray.EMPTY_INTS; - mArray = SparseArray.EMPTY_OBJECTS; + mHashes = ContainerHelpers.EMPTY_INTS; + mArray = ContainerHelpers.EMPTY_OBJECTS; mSize = 0; } else { if (mHashes.length > (BASE_SIZE*2) && mSize < mHashes.length/3) { diff --git a/core/java/android/util/ContainerHelpers.java b/core/java/android/util/ContainerHelpers.java new file mode 100644 index 0000000..624c4bd --- /dev/null +++ b/core/java/android/util/ContainerHelpers.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +class ContainerHelpers { + static final boolean[] EMPTY_BOOLEANS = new boolean[0]; + static final int[] EMPTY_INTS = new int[0]; + static final long[] EMPTY_LONGS = new long[0]; + static final Object[] EMPTY_OBJECTS = new Object[0]; + + // This is Arrays.binarySearch(), but doesn't do any argument validation. + static int binarySearch(int[] array, int size, int value) { + int lo = 0; + int hi = size - 1; + + while (lo <= hi) { + final int mid = (lo + hi) >>> 1; + final int midVal = array[mid]; + + if (midVal < value) { + lo = mid + 1; + } else if (midVal > value) { + hi = mid - 1; + } else { + return mid; // value found + } + } + return ~lo; // value not present + } + + static int binarySearch(long[] array, int size, long value) { + int lo = 0; + int hi = size - 1; + + while (lo <= hi) { + final int mid = (lo + hi) >>> 1; + final long midVal = array[mid]; + + if (midVal < value) { + lo = mid + 1; + } else if (midVal > value) { + hi = mid - 1; + } else { + return mid; // value found + } + } + return ~lo; // value not present + } +} diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java index 77dfcf4..63e8c25 100644 --- a/core/java/android/util/LongSparseArray.java +++ b/core/java/android/util/LongSparseArray.java @@ -64,8 +64,8 @@ public class LongSparseArray<E> implements Cloneable { */ public LongSparseArray(int initialCapacity) { if (initialCapacity == 0) { - mKeys = SparseLongArray.EMPTY_LONGS; - mValues = SparseArray.EMPTY_OBJECTS; + mKeys = ContainerHelpers.EMPTY_LONGS; + mValues = ContainerHelpers.EMPTY_OBJECTS; } else { initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity); mKeys = new long[initialCapacity]; @@ -102,7 +102,7 @@ public class LongSparseArray<E> implements Cloneable { */ @SuppressWarnings("unchecked") public E get(long key, E valueIfKeyNotFound) { - int i = binarySearch(mKeys, 0, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i < 0 || mValues[i] == DELETED) { return valueIfKeyNotFound; @@ -115,7 +115,7 @@ public class LongSparseArray<E> implements Cloneable { * Removes the mapping from the specified key, if there was any. */ public void delete(long key) { - int i = binarySearch(mKeys, 0, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { if (mValues[i] != DELETED) { @@ -176,7 +176,7 @@ public class LongSparseArray<E> implements Cloneable { * was one. */ public void put(long key, E value) { - int i = binarySearch(mKeys, 0, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { mValues[i] = value; @@ -193,7 +193,7 @@ public class LongSparseArray<E> implements Cloneable { gc(); // Search again because indices may have changed. - i = ~binarySearch(mKeys, 0, mSize, key); + i = ~ContainerHelpers.binarySearch(mKeys, mSize, key); } if (mSize >= mKeys.length) { @@ -284,7 +284,7 @@ public class LongSparseArray<E> implements Cloneable { gc(); } - return binarySearch(mKeys, 0, mSize, key); + return ContainerHelpers.binarySearch(mKeys, mSize, key); } /** @@ -356,23 +356,36 @@ public class LongSparseArray<E> implements Cloneable { mSize = pos + 1; } - private static int binarySearch(long[] a, int start, int len, long key) { - int high = start + len, low = start - 1, guess; - - while (high - low > 1) { - guess = (high + low) / 2; - - if (a[guess] < key) - low = guess; - else - high = guess; + /** + * {@inheritDoc} + * + * <p>This implementation composes a string by iterating over its mappings. If + * this map contains itself as a value, the string "(this Map)" + * will appear in its place. + */ + @Override + public String toString() { + if (size() <= 0) { + return "{}"; } - if (high == start + len) - return ~(start + len); - else if (a[high] == key) - return high; - else - return ~high; + StringBuilder buffer = new StringBuilder(mSize * 28); + buffer.append('{'); + for (int i=0; i<mSize; i++) { + if (i > 0) { + buffer.append(", "); + } + long key = keyAt(i); + buffer.append(key); + buffer.append('='); + Object value = valueAt(i); + if (value != this) { + buffer.append(value); + } else { + buffer.append("(this Map)"); + } + } + buffer.append('}'); + return buffer.toString(); } } diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java index d795308..133e415 100644 --- a/core/java/android/util/LongSparseLongArray.java +++ b/core/java/android/util/LongSparseLongArray.java @@ -58,8 +58,8 @@ public class LongSparseLongArray implements Cloneable { */ public LongSparseLongArray(int initialCapacity) { if (initialCapacity == 0) { - mKeys = SparseLongArray.EMPTY_LONGS; - mValues = SparseLongArray.EMPTY_LONGS; + mKeys = ContainerHelpers.EMPTY_LONGS; + mValues = ContainerHelpers.EMPTY_LONGS; } else { initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity); mKeys = new long[initialCapacity]; @@ -94,7 +94,7 @@ public class LongSparseLongArray implements Cloneable { * if no such mapping has been made. */ public long get(long key, long valueIfKeyNotFound) { - int i = Arrays.binarySearch(mKeys, 0, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i < 0) { return valueIfKeyNotFound; @@ -107,7 +107,7 @@ public class LongSparseLongArray implements Cloneable { * Removes the mapping from the specified key, if there was any. */ public void delete(long key) { - int i = Arrays.binarySearch(mKeys, 0, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { removeAt(i); @@ -129,7 +129,7 @@ public class LongSparseLongArray implements Cloneable { * was one. */ public void put(long key, long value) { - int i = Arrays.binarySearch(mKeys, 0, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { mValues[i] = value; @@ -183,7 +183,7 @@ public class LongSparseLongArray implements Cloneable { * key is not mapped. */ public int indexOfKey(long key) { - return Arrays.binarySearch(mKeys, 0, mSize, key); + return ContainerHelpers.binarySearch(mKeys, mSize, key); } /** @@ -241,4 +241,31 @@ public class LongSparseLongArray implements Cloneable { mKeys = nkeys; mValues = nvalues; } + + /** + * {@inheritDoc} + * + * <p>This implementation composes a string by iterating over its mappings. + */ + @Override + public String toString() { + if (size() <= 0) { + return "{}"; + } + + StringBuilder buffer = new StringBuilder(mSize * 28); + buffer.append('{'); + for (int i=0; i<mSize; i++) { + if (i > 0) { + buffer.append(", "); + } + long key = keyAt(i); + buffer.append(key); + buffer.append('='); + long value = valueAt(i); + buffer.append(value); + } + buffer.append('}'); + return buffer.toString(); + } } diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java index 0e013c3..6e66090 100644 --- a/core/java/android/util/SparseArray.java +++ b/core/java/android/util/SparseArray.java @@ -42,8 +42,6 @@ import com.android.internal.util.ArrayUtils; */ public class SparseArray<E> implements Cloneable { private static final Object DELETED = new Object(); - static final int[] EMPTY_INTS = new int[0]; - static final Object[] EMPTY_OBJECTS = new Object[0]; private boolean mGarbage = false; private int[] mKeys; @@ -66,8 +64,8 @@ public class SparseArray<E> implements Cloneable { */ public SparseArray(int initialCapacity) { if (initialCapacity == 0) { - mKeys = EMPTY_INTS; - mValues = EMPTY_OBJECTS; + mKeys = ContainerHelpers.EMPTY_INTS; + mValues = ContainerHelpers.EMPTY_OBJECTS; } else { initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity); mKeys = new int[initialCapacity]; @@ -104,7 +102,7 @@ public class SparseArray<E> implements Cloneable { */ @SuppressWarnings("unchecked") public E get(int key, E valueIfKeyNotFound) { - int i = binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i < 0 || mValues[i] == DELETED) { return valueIfKeyNotFound; @@ -117,7 +115,7 @@ public class SparseArray<E> implements Cloneable { * Removes the mapping from the specified key, if there was any. */ public void delete(int key) { - int i = binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { if (mValues[i] != DELETED) { @@ -144,6 +142,19 @@ public class SparseArray<E> implements Cloneable { } } + /** + * Remove a range of mappings as a batch. + * + * @param index Index to begin at + * @param size Number of mappings to remove + */ + public void removeAtRange(int index, int size) { + final int end = Math.min(mSize, index + size); + for (int i = index; i < end; i++) { + removeAt(i); + } + } + private void gc() { // Log.e("SparseArray", "gc start with " + mSize); @@ -178,7 +189,7 @@ public class SparseArray<E> implements Cloneable { * was one. */ public void put(int key, E value) { - int i = binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { mValues[i] = value; @@ -195,7 +206,7 @@ public class SparseArray<E> implements Cloneable { gc(); // Search again because indices may have changed. - i = ~binarySearch(mKeys, mSize, key); + i = ~ContainerHelpers.binarySearch(mKeys, mSize, key); } if (mSize >= mKeys.length) { @@ -286,7 +297,7 @@ public class SparseArray<E> implements Cloneable { gc(); } - return binarySearch(mKeys, mSize, key); + return ContainerHelpers.binarySearch(mKeys, mSize, key); } /** @@ -360,23 +371,36 @@ public class SparseArray<E> implements Cloneable { mSize = pos + 1; } - // This is Arrays.binarySearch(), but doesn't do any argument validation. - static int binarySearch(int[] array, int size, int value) { - int lo = 0; - int hi = size - 1; - - while (lo <= hi) { - int mid = (lo + hi) >>> 1; - int midVal = array[mid]; + /** + * {@inheritDoc} + * + * <p>This implementation composes a string by iterating over its mappings. If + * this map contains itself as a value, the string "(this Map)" + * will appear in its place. + */ + @Override + public String toString() { + if (size() <= 0) { + return "{}"; + } - if (midVal < value) { - lo = mid + 1; - } else if (midVal > value) { - hi = mid - 1; + StringBuilder buffer = new StringBuilder(mSize * 28); + buffer.append('{'); + for (int i=0; i<mSize; i++) { + if (i > 0) { + buffer.append(", "); + } + int key = keyAt(i); + buffer.append(key); + buffer.append('='); + Object value = valueAt(i); + if (value != this) { + buffer.append(value); } else { - return mid; // value found + buffer.append("(this Map)"); } } - return ~lo; // value not present + buffer.append('}'); + return buffer.toString(); } } diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java index 430755a..da196d7 100644 --- a/core/java/android/util/SparseBooleanArray.java +++ b/core/java/android/util/SparseBooleanArray.java @@ -35,8 +35,6 @@ import com.android.internal.util.ArrayUtils; * the performance difference is not significant, less than 50%.</p> */ public class SparseBooleanArray implements Cloneable { - static final boolean[] EMPTY_BOOLEANS = new boolean[0]; - /** * Creates a new SparseBooleanArray containing no mappings. */ @@ -53,8 +51,8 @@ public class SparseBooleanArray implements Cloneable { */ public SparseBooleanArray(int initialCapacity) { if (initialCapacity == 0) { - mKeys = SparseArray.EMPTY_INTS; - mValues = EMPTY_BOOLEANS; + mKeys = ContainerHelpers.EMPTY_INTS; + mValues = ContainerHelpers.EMPTY_BOOLEANS; } else { initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity); mKeys = new int[initialCapacity]; @@ -89,7 +87,7 @@ public class SparseBooleanArray implements Cloneable { * if no such mapping has been made. */ public boolean get(int key, boolean valueIfKeyNotFound) { - int i = SparseArray.binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i < 0) { return valueIfKeyNotFound; @@ -102,7 +100,7 @@ public class SparseBooleanArray implements Cloneable { * Removes the mapping from the specified key, if there was any. */ public void delete(int key) { - int i = SparseArray.binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { System.arraycopy(mKeys, i + 1, mKeys, i, mSize - (i + 1)); @@ -117,7 +115,7 @@ public class SparseBooleanArray implements Cloneable { * was one. */ public void put(int key, boolean value) { - int i = SparseArray.binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { mValues[i] = value; @@ -182,7 +180,7 @@ public class SparseBooleanArray implements Cloneable { * key is not mapped. */ public int indexOfKey(int key) { - return SparseArray.binarySearch(mKeys, mSize, key); + return ContainerHelpers.binarySearch(mKeys, mSize, key); } /** @@ -237,7 +235,34 @@ public class SparseBooleanArray implements Cloneable { mValues[pos] = value; mSize = pos + 1; } - + + /** + * {@inheritDoc} + * + * <p>This implementation composes a string by iterating over its mappings. + */ + @Override + public String toString() { + if (size() <= 0) { + return "{}"; + } + + StringBuilder buffer = new StringBuilder(mSize * 28); + buffer.append('{'); + for (int i=0; i<mSize; i++) { + if (i > 0) { + buffer.append(", "); + } + int key = keyAt(i); + buffer.append(key); + buffer.append('='); + boolean value = valueAt(i); + buffer.append(value); + } + buffer.append('}'); + return buffer.toString(); + } + private int[] mKeys; private boolean[] mValues; private int mSize; diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java index b6fb295..c2bacb0 100644 --- a/core/java/android/util/SparseIntArray.java +++ b/core/java/android/util/SparseIntArray.java @@ -54,8 +54,8 @@ public class SparseIntArray implements Cloneable { */ public SparseIntArray(int initialCapacity) { if (initialCapacity == 0) { - mKeys = SparseArray.EMPTY_INTS; - mValues = SparseArray.EMPTY_INTS; + mKeys = ContainerHelpers.EMPTY_INTS; + mValues = ContainerHelpers.EMPTY_INTS; } else { initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity); mKeys = new int[initialCapacity]; @@ -90,7 +90,7 @@ public class SparseIntArray implements Cloneable { * if no such mapping has been made. */ public int get(int key, int valueIfKeyNotFound) { - int i = SparseArray.binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i < 0) { return valueIfKeyNotFound; @@ -103,7 +103,7 @@ public class SparseIntArray implements Cloneable { * Removes the mapping from the specified key, if there was any. */ public void delete(int key) { - int i = SparseArray.binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { removeAt(i); @@ -125,7 +125,7 @@ public class SparseIntArray implements Cloneable { * was one. */ public void put(int key, int value) { - int i = SparseArray.binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { mValues[i] = value; @@ -190,7 +190,7 @@ public class SparseIntArray implements Cloneable { * key is not mapped. */ public int indexOfKey(int key) { - return SparseArray.binarySearch(mKeys, mSize, key); + return ContainerHelpers.binarySearch(mKeys, mSize, key); } /** @@ -245,4 +245,31 @@ public class SparseIntArray implements Cloneable { mValues[pos] = value; mSize = pos + 1; } + + /** + * {@inheritDoc} + * + * <p>This implementation composes a string by iterating over its mappings. + */ + @Override + public String toString() { + if (size() <= 0) { + return "{}"; + } + + StringBuilder buffer = new StringBuilder(mSize * 28); + buffer.append('{'); + for (int i=0; i<mSize; i++) { + if (i > 0) { + buffer.append(", "); + } + int key = keyAt(i); + buffer.append(key); + buffer.append('='); + int value = valueAt(i); + buffer.append(value); + } + buffer.append('}'); + return buffer.toString(); + } } diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java index 55cb3a2..182fd35 100644 --- a/core/java/android/util/SparseLongArray.java +++ b/core/java/android/util/SparseLongArray.java @@ -34,8 +34,6 @@ import com.android.internal.util.ArrayUtils; * the performance difference is not significant, less than 50%.</p> */ public class SparseLongArray implements Cloneable { - static final long[] EMPTY_LONGS = new long[0]; - private int[] mKeys; private long[] mValues; private int mSize; @@ -56,8 +54,8 @@ public class SparseLongArray implements Cloneable { */ public SparseLongArray(int initialCapacity) { if (initialCapacity == 0) { - mKeys = SparseArray.EMPTY_INTS; - mValues = EMPTY_LONGS; + mKeys = ContainerHelpers.EMPTY_INTS; + mValues = ContainerHelpers.EMPTY_LONGS; } else { initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity); mKeys = new int[initialCapacity]; @@ -92,7 +90,7 @@ public class SparseLongArray implements Cloneable { * if no such mapping has been made. */ public long get(int key, long valueIfKeyNotFound) { - int i = SparseArray.binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i < 0) { return valueIfKeyNotFound; @@ -105,7 +103,7 @@ public class SparseLongArray implements Cloneable { * Removes the mapping from the specified key, if there was any. */ public void delete(int key) { - int i = SparseArray.binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { removeAt(i); @@ -127,7 +125,7 @@ public class SparseLongArray implements Cloneable { * was one. */ public void put(int key, long value) { - int i = SparseArray.binarySearch(mKeys, mSize, key); + int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { mValues[i] = value; @@ -181,7 +179,7 @@ public class SparseLongArray implements Cloneable { * key is not mapped. */ public int indexOfKey(int key) { - return SparseArray.binarySearch(mKeys, mSize, key); + return ContainerHelpers.binarySearch(mKeys, mSize, key); } /** @@ -239,4 +237,31 @@ public class SparseLongArray implements Cloneable { mKeys = nkeys; mValues = nvalues; } + + /** + * {@inheritDoc} + * + * <p>This implementation composes a string by iterating over its mappings. + */ + @Override + public String toString() { + if (size() <= 0) { + return "{}"; + } + + StringBuilder buffer = new StringBuilder(mSize * 28); + buffer.append('{'); + for (int i=0; i<mSize; i++) { + if (i > 0) { + buffer.append(", "); + } + int key = keyAt(i); + buffer.append(key); + buffer.append('='); + long value = valueAt(i); + buffer.append(value); + } + buffer.append('}'); + return buffer.toString(); + } } |