Home | History | Annotate | Download | only in util
      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 
     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      */
     45     public IntArray() {
     46         this(10);
     47     }
     48 
     49     /**
     50      * Creates an empty IntArray with the specified initial capacity.
     51      */
     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      */
     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      */
     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      */
     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      */
     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 &lt; 0 || index &gt; size()
    102      */
    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      */
    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      */
    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      */
    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      */
    165     public void clear() {
    166         mSize = 0;
    167     }
    168 
    169     @Override
    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      */
    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      */
    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      */
    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      */
    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      */
    218     public int size() {
    219         return mSize;
    220     }
    221 
    222     /**
    223      * Returns a new array with the contents of this IntArray.
    224      */
    225     public int[] toArray() {
    226         return Arrays.copyOf(mValues, mSize);
    227     }
    228 }
    229