• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 
17 package com.android.sdklib.util;
18 
19 
20 /**
21  * SparseIntArrays map integers to integers.  Unlike a normal array of integers,
22  * there can be gaps in the indices.  It is intended to be more efficient
23  * than using a HashMap to map Integers to Integers.
24  */
25 public class SparseIntArray {
26     /**
27      * Creates a new SparseIntArray containing no mappings.
28      */
SparseIntArray()29     public SparseIntArray() {
30         this(10);
31     }
32 
33     /**
34      * Creates a new SparseIntArray containing no mappings that will not
35      * require any additional memory allocation to store the specified
36      * number of mappings.
37      */
SparseIntArray(int initialCapacity)38     public SparseIntArray(int initialCapacity) {
39         initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
40 
41         mKeys = new int[initialCapacity];
42         mValues = new int[initialCapacity];
43         mSize = 0;
44     }
45 
46     /**
47      * Gets the int mapped from the specified key, or <code>0</code>
48      * if no such mapping has been made.
49      */
get(int key)50     public int get(int key) {
51         return get(key, 0);
52     }
53 
54     /**
55      * Gets the int mapped from the specified key, or the specified value
56      * if no such mapping has been made.
57      */
get(int key, int valueIfKeyNotFound)58     public int get(int key, int valueIfKeyNotFound) {
59         int i = binarySearch(mKeys, 0, mSize, key);
60 
61         if (i < 0) {
62             return valueIfKeyNotFound;
63         } else {
64             return mValues[i];
65         }
66     }
67 
68     /**
69      * Removes the mapping from the specified key, if there was any.
70      */
delete(int key)71     public void delete(int key) {
72         int i = binarySearch(mKeys, 0, mSize, key);
73 
74         if (i >= 0) {
75             removeAt(i);
76         }
77     }
78 
79     /**
80      * Removes the mapping at the given index.
81      */
removeAt(int index)82     public void removeAt(int index) {
83         System.arraycopy(mKeys, index + 1, mKeys, index, mSize - (index + 1));
84         System.arraycopy(mValues, index + 1, mValues, index, mSize - (index + 1));
85         mSize--;
86     }
87 
88     /**
89      * Adds a mapping from the specified key to the specified value,
90      * replacing the previous mapping from the specified key if there
91      * was one.
92      */
put(int key, int value)93     public void put(int key, int value) {
94         int i = binarySearch(mKeys, 0, mSize, key);
95 
96         if (i >= 0) {
97             mValues[i] = value;
98         } else {
99             i = ~i;
100 
101             if (mSize >= mKeys.length) {
102                 int n = ArrayUtils.idealIntArraySize(mSize + 1);
103 
104                 int[] nkeys = new int[n];
105                 int[] nvalues = new int[n];
106 
107                 // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n);
108                 System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
109                 System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
110 
111                 mKeys = nkeys;
112                 mValues = nvalues;
113             }
114 
115             if (mSize - i != 0) {
116                 // Log.e("SparseIntArray", "move " + (mSize - i));
117                 System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
118                 System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
119             }
120 
121             mKeys[i] = key;
122             mValues[i] = value;
123             mSize++;
124         }
125     }
126 
127     /**
128      * Returns the number of key-value mappings that this SparseIntArray
129      * currently stores.
130      */
size()131     public int size() {
132         return mSize;
133     }
134 
135     /**
136      * Given an index in the range <code>0...size()-1</code>, returns
137      * the key from the <code>index</code>th key-value mapping that this
138      * SparseIntArray stores.
139      */
keyAt(int index)140     public int keyAt(int index) {
141         return mKeys[index];
142     }
143 
144     /**
145      * Given an index in the range <code>0...size()-1</code>, returns
146      * the value from the <code>index</code>th key-value mapping that this
147      * SparseIntArray stores.
148      */
valueAt(int index)149     public int valueAt(int index) {
150         return mValues[index];
151     }
152 
153     /**
154      * Returns the index for which {@link #keyAt} would return the
155      * specified key, or a negative number if the specified
156      * key is not mapped.
157      */
indexOfKey(int key)158     public int indexOfKey(int key) {
159         return binarySearch(mKeys, 0, mSize, key);
160     }
161 
162     /**
163      * Returns an index for which {@link #valueAt} would return the
164      * specified key, or a negative number if no keys map to the
165      * specified value.
166      * Beware that this is a linear search, unlike lookups by key,
167      * and that multiple keys can map to the same value and this will
168      * find only one of them.
169      */
indexOfValue(int value)170     public int indexOfValue(int value) {
171         for (int i = 0; i < mSize; i++)
172             if (mValues[i] == value)
173                 return i;
174 
175         return -1;
176     }
177 
178     /**
179      * Removes all key-value mappings from this SparseIntArray.
180      */
clear()181     public void clear() {
182         mSize = 0;
183     }
184 
185     /**
186      * Puts a key/value pair into the array, optimizing for the case where
187      * the key is greater than all existing keys in the array.
188      */
append(int key, int value)189     public void append(int key, int value) {
190         if (mSize != 0 && key <= mKeys[mSize - 1]) {
191             put(key, value);
192             return;
193         }
194 
195         int pos = mSize;
196         if (pos >= mKeys.length) {
197             int n = ArrayUtils.idealIntArraySize(pos + 1);
198 
199             int[] nkeys = new int[n];
200             int[] nvalues = new int[n];
201 
202             // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n);
203             System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
204             System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
205 
206             mKeys = nkeys;
207             mValues = nvalues;
208         }
209 
210         mKeys[pos] = key;
211         mValues[pos] = value;
212         mSize = pos + 1;
213     }
214 
binarySearch(int[] a, int start, int len, int key)215     private static int binarySearch(int[] a, int start, int len, int key) {
216         int high = start + len, low = start - 1, guess;
217 
218         while (high - low > 1) {
219             guess = (high + low) / 2;
220 
221             if (a[guess] < key)
222                 low = guess;
223             else
224                 high = guess;
225         }
226 
227         if (high == start + len)
228             return ~(start + len);
229         else if (a[high] == key)
230             return high;
231         else
232             return ~high;
233     }
234 
235     private int[] mKeys;
236     private int[] mValues;
237     private int mSize;
238 }
239