1 /* 2 * Copyright (C) 2014 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 import com.android.internal.util.Preconditions; 21 22 import libcore.util.EmptyArray; 23 24 import java.util.Arrays; 25 26 /** 27 * Implements a growing array of int primitives. 28 * 29 * @hide 30 */ 31 public class IntArray implements Cloneable { 32 private static final int MIN_CAPACITY_INCREMENT = 12; 33 34 private int[] mValues; 35 private int mSize; 36 IntArray(int[] array, int size)37 private IntArray(int[] array, int size) { 38 mValues = array; 39 mSize = Preconditions.checkArgumentInRange(size, 0, array.length, "size"); 40 } 41 42 /** 43 * Creates an empty IntArray with the default initial capacity. 44 */ IntArray()45 public IntArray() { 46 this(10); 47 } 48 49 /** 50 * Creates an empty IntArray with the specified initial capacity. 51 */ IntArray(int initialCapacity)52 public IntArray(int initialCapacity) { 53 if (initialCapacity == 0) { 54 mValues = EmptyArray.INT; 55 } else { 56 mValues = ArrayUtils.newUnpaddedIntArray(initialCapacity); 57 } 58 mSize = 0; 59 } 60 61 /** 62 * Creates an IntArray wrapping the given primitive int array. 63 */ wrap(int[] array)64 public static IntArray wrap(int[] array) { 65 return new IntArray(array, array.length); 66 } 67 68 /** 69 * Creates an IntArray from the given primitive int array, copying it. 70 */ fromArray(int[] array, int size)71 public static IntArray fromArray(int[] array, int size) { 72 return wrap(Arrays.copyOf(array, size)); 73 } 74 75 /** 76 * Changes the size of this IntArray. If this IntArray is shrinked, the backing array capacity 77 * is unchanged. If the new size is larger than backing array capacity, a new backing array is 78 * created from the current content of this IntArray padded with 0s. 79 */ resize(int newSize)80 public void resize(int newSize) { 81 Preconditions.checkArgumentNonnegative(newSize); 82 if (newSize <= mValues.length) { 83 Arrays.fill(mValues, newSize, mValues.length, 0); 84 } else { 85 ensureCapacity(newSize - mSize); 86 } 87 mSize = newSize; 88 } 89 90 /** 91 * Appends the specified value to the end of this array. 92 */ add(int value)93 public void add(int value) { 94 add(mSize, value); 95 } 96 97 /** 98 * Inserts a value at the specified position in this array. If the specified index is equal to 99 * the length of the array, the value is added at the end. 100 * 101 * @throws IndexOutOfBoundsException when index < 0 || index > size() 102 */ add(int index, int value)103 public void add(int index, int value) { 104 ensureCapacity(1); 105 int rightSegment = mSize - index; 106 mSize++; 107 ArrayUtils.checkBounds(mSize, index); 108 109 if (rightSegment != 0) { 110 // Move by 1 all values from the right of 'index' 111 System.arraycopy(mValues, index, mValues, index + 1, rightSegment); 112 } 113 114 mValues[index] = value; 115 } 116 117 /** 118 * Searches the array for the specified value using the binary search algorithm. The array must 119 * be sorted (as by the {@link Arrays#sort(int[], int, int)} method) prior to making this call. 120 * If it is not sorted, the results are undefined. If the range contains multiple elements with 121 * the specified value, there is no guarantee which one will be found. 122 * 123 * @param value The value to search for. 124 * @return index of the search key, if it is contained in the array; otherwise, <i>(-(insertion 125 * point) - 1)</i>. The insertion point is defined as the point at which the key would 126 * be inserted into the array: the index of the first element greater than the key, or 127 * {@link #size()} if all elements in the array are less than the specified key. 128 * Note that this guarantees that the return value will be >= 0 if and only if the key 129 * is found. 130 */ binarySearch(int value)131 public int binarySearch(int value) { 132 return ContainerHelpers.binarySearch(mValues, mSize, value); 133 } 134 135 /** 136 * Adds the values in the specified array to this array. 137 */ addAll(IntArray values)138 public void addAll(IntArray values) { 139 final int count = values.mSize; 140 ensureCapacity(count); 141 142 System.arraycopy(values.mValues, 0, mValues, mSize, count); 143 mSize += count; 144 } 145 146 /** 147 * Ensures capacity to append at least <code>count</code> values. 148 */ ensureCapacity(int count)149 private void ensureCapacity(int count) { 150 final int currentSize = mSize; 151 final int minCapacity = currentSize + count; 152 if (minCapacity >= mValues.length) { 153 final int targetCap = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) ? 154 MIN_CAPACITY_INCREMENT : currentSize >> 1); 155 final int newCapacity = targetCap > minCapacity ? targetCap : minCapacity; 156 final int[] newValues = ArrayUtils.newUnpaddedIntArray(newCapacity); 157 System.arraycopy(mValues, 0, newValues, 0, currentSize); 158 mValues = newValues; 159 } 160 } 161 162 /** 163 * Removes all values from this array. 164 */ clear()165 public void clear() { 166 mSize = 0; 167 } 168 169 @Override clone()170 public IntArray clone() throws CloneNotSupportedException { 171 final IntArray clone = (IntArray) super.clone(); 172 clone.mValues = mValues.clone(); 173 return clone; 174 } 175 176 /** 177 * Returns the value at the specified position in this array. 178 */ get(int index)179 public int get(int index) { 180 ArrayUtils.checkBounds(mSize, index); 181 return mValues[index]; 182 } 183 184 /** 185 * Sets the value at the specified position in this array. 186 */ set(int index, int value)187 public void set(int index, int value) { 188 ArrayUtils.checkBounds(mSize, index); 189 mValues[index] = value; 190 } 191 192 /** 193 * Returns the index of the first occurrence of the specified value in this 194 * array, or -1 if this array does not contain the value. 195 */ indexOf(int value)196 public int indexOf(int value) { 197 final int n = mSize; 198 for (int i = 0; i < n; i++) { 199 if (mValues[i] == value) { 200 return i; 201 } 202 } 203 return -1; 204 } 205 206 /** 207 * Removes the value at the specified index from this array. 208 */ remove(int index)209 public void remove(int index) { 210 ArrayUtils.checkBounds(mSize, index); 211 System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1); 212 mSize--; 213 } 214 215 /** 216 * Returns the number of values in this array. 217 */ size()218 public int size() { 219 return mSize; 220 } 221 222 /** 223 * Returns a new array with the contents of this IntArray. 224 */ toArray()225 public int[] toArray() { 226 return Arrays.copyOf(mValues, mSize); 227 } 228 } 229