1 package jalview.ext.android;
4 * Copyright (C) 2006 The Android Open Source Project
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 * SparseIntArrays map integers to integers. Unlike a normal array of integers,
20 * there can be gaps in the indices. It is intended to be more memory efficient
21 * than using a HashMap to map Integers to Integers, both because it avoids
22 * auto-boxing keys and values and its data structure doesn't rely on an extra
23 * entry object for each mapping.
26 * Note that this container keeps its mappings in an array data structure, using
27 * a binary search to find keys. The implementation is not intended to be
28 * appropriate for data structures that may contain large numbers of items. It
29 * is generally slower than a traditional HashMap, since lookups require a
30 * binary search and adds and removes require inserting and deleting entries in
31 * the array. For containers holding up to hundreds of items, the performance
32 * difference is not significant, less than 50%.
36 * It is possible to iterate over the items in this container using
37 * {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using
38 * <code>keyAt(int)</code> with ascending values of the index will return the
39 * keys in ascending order, or the values corresponding to the keys in ascending
40 * order in the case of <code>valueAt(int)<code>.
43 public class SparseIntArray implements Cloneable
47 private int[] mValues;
52 * Creates a new SparseIntArray containing no mappings.
54 public SparseIntArray()
60 * Creates a new SparseIntArray containing no mappings that will not require
61 * any additional memory allocation to store the specified number of mappings.
62 * If you supply an initial capacity of 0, the sparse array will be
63 * initialized with a light-weight representation not requiring any additional
66 public SparseIntArray(int initialCapacity)
68 if (initialCapacity == 0)
70 mKeys = ContainerHelpers.EMPTY_INTS;
71 mValues = ContainerHelpers.EMPTY_INTS;
75 initialCapacity = idealIntArraySize(initialCapacity);
76 mKeys = new int[initialCapacity];
77 mValues = new int[initialCapacity];
83 public SparseIntArray clone()
85 SparseIntArray clone = null;
88 clone = (SparseIntArray) super.clone();
89 clone.mKeys = mKeys.clone();
90 clone.mValues = mValues.clone();
91 } catch (CloneNotSupportedException cnse)
99 * Gets the int mapped from the specified key, or <code>0</code> if no such
100 * mapping has been made.
102 public int get(int key)
108 * Gets the int mapped from the specified key, or the specified value if no
109 * such mapping has been made.
111 public int get(int key, int valueIfKeyNotFound)
113 int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
116 return valueIfKeyNotFound;
125 * Removes the mapping from the specified key, if there was any.
127 public void delete(int key)
129 int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
137 * Removes the mapping at the given index.
139 public void removeAt(int index)
141 System.arraycopy(mKeys, index + 1, mKeys, index, mSize - (index + 1));
142 System.arraycopy(mValues, index + 1, mValues, index, mSize
148 * Adds a mapping from the specified key to the specified value, replacing the
149 * previous mapping from the specified key if there was one.
151 public void put(int key, int value)
153 int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
161 if (mSize >= mKeys.length)
163 int n = idealIntArraySize(mSize + 1);
164 int[] nkeys = new int[n];
165 int[] nvalues = new int[n];
166 // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n);
167 System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
168 System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
174 // Log.e("SparseIntArray", "move " + (mSize - i));
175 System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
176 System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
185 * Returns the number of key-value mappings that this SparseIntArray currently
194 * Given an index in the range <code>0...size()-1</code>, returns the key from
195 * the <code>index</code>th key-value mapping that this SparseIntArray stores.
198 * The keys corresponding to indices in ascending order are guaranteed to be
199 * in ascending order, e.g., <code>keyAt(0)</code> will return the smallest
200 * key and <code>keyAt(size()-1)</code> will return the largest key.
203 public int keyAt(int index)
209 * Given an index in the range <code>0...size()-1</code>, returns the value
210 * from the <code>index</code>th key-value mapping that this SparseIntArray
214 * The values corresponding to indices in ascending order are guaranteed to be
215 * associated with keys in ascending order, e.g., <code>valueAt(0)</code> will
216 * return the value associated with the smallest key and
217 * <code>valueAt(size()-1)</code> will return the value associated with the
221 public int valueAt(int index)
223 return mValues[index];
227 * Returns the index for which {@link #keyAt} would return the specified key,
228 * or a negative number if the specified key is not mapped.
230 public int indexOfKey(int key)
232 return ContainerHelpers.binarySearch(mKeys, mSize, key);
236 * Returns an index for which {@link #valueAt} would return the specified key,
237 * or a negative number if no keys map to the specified value. Beware that
238 * this is a linear search, unlike lookups by key, and that multiple keys can
239 * map to the same value and this will find only one of them.
241 public int indexOfValue(int value)
243 for (int i = 0; i < mSize; i++)
245 if (mValues[i] == value)
254 * Removes all key-value mappings from this SparseIntArray.
262 * Puts a key/value pair into the array, optimizing for the case where the key
263 * is greater than all existing keys in the array.
265 public void append(int key, int value)
267 if (mSize != 0 && key <= mKeys[mSize - 1])
273 if (pos >= mKeys.length)
275 int n = idealIntArraySize(pos + 1);
276 int[] nkeys = new int[n];
277 int[] nvalues = new int[n];
278 // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n);
279 System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
280 System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
285 mValues[pos] = value;
290 * Inlined here by copying from com.android.internal.util.ArrayUtils
295 public static int idealIntArraySize(int need)
297 return idealByteArraySize(need * 4) / 4;
301 * Inlined here by copying from com.android.internal.util.ArrayUtils
306 public static int idealByteArraySize(int need)
308 for (int i = 4; i < 32; i++)
310 if (need <= (1 << i) - 12)
312 return (1 << i) - 12;
323 * This implementation composes a string by iterating over its mappings.
326 public String toString()
332 StringBuilder buffer = new StringBuilder(mSize * 28);
334 for (int i = 0; i < mSize; i++)
343 int value = valueAt(i);
344 buffer.append(value);
347 return buffer.toString();