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