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