Home | History | Annotate | Download | only in primitives
      1 /*
      2  * Copyright (C) 2008 The Guava Authors
      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.google.common.primitives;
     18 
     19 import static com.google.common.base.Preconditions.checkArgument;
     20 import static com.google.common.base.Preconditions.checkElementIndex;
     21 import static com.google.common.base.Preconditions.checkNotNull;
     22 import static com.google.common.base.Preconditions.checkPositionIndexes;
     23 
     24 import com.google.common.annotations.Beta;
     25 import com.google.common.annotations.GwtCompatible;
     26 import com.google.common.annotations.GwtIncompatible;
     27 
     28 import java.io.Serializable;
     29 import java.util.AbstractList;
     30 import java.util.Arrays;
     31 import java.util.Collection;
     32 import java.util.Collections;
     33 import java.util.Comparator;
     34 import java.util.List;
     35 import java.util.RandomAccess;
     36 
     37 import javax.annotation.CheckForNull;
     38 
     39 /**
     40  * Static utility methods pertaining to {@code int} primitives, that are not
     41  * already found in either {@link Integer} or {@link Arrays}.
     42  *
     43  * @author Kevin Bourrillion
     44  * @since 1.0
     45  */
     46 @GwtCompatible(emulated = true)
     47 public final class Ints {
     48   private Ints() {}
     49 
     50   /**
     51    * The number of bytes required to represent a primitive {@code int}
     52    * value.
     53    */
     54   public static final int BYTES = Integer.SIZE / Byte.SIZE;
     55 
     56   /**
     57    * The largest power of two that can be represented as an {@code int}.
     58    *
     59    * @since 10.0
     60    */
     61   public static final int MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2);
     62 
     63   /**
     64    * Returns a hash code for {@code value}; equal to the result of invoking
     65    * {@code ((Integer) value).hashCode()}.
     66    *
     67    * @param value a primitive {@code int} value
     68    * @return a hash code for the value
     69    */
     70   public static int hashCode(int value) {
     71     return value;
     72   }
     73 
     74   /**
     75    * Returns the {@code int} value that is equal to {@code value}, if possible.
     76    *
     77    * @param value any value in the range of the {@code int} type
     78    * @return the {@code int} value that equals {@code value}
     79    * @throws IllegalArgumentException if {@code value} is greater than {@link
     80    *     Integer#MAX_VALUE} or less than {@link Integer#MIN_VALUE}
     81    */
     82   public static int checkedCast(long value) {
     83     int result = (int) value;
     84     checkArgument(result == value, "Out of range: %s", value);
     85     return result;
     86   }
     87 
     88   /**
     89    * Returns the {@code int} nearest in value to {@code value}.
     90    *
     91    * @param value any {@code long} value
     92    * @return the same value cast to {@code int} if it is in the range of the
     93    *     {@code int} type, {@link Integer#MAX_VALUE} if it is too large,
     94    *     or {@link Integer#MIN_VALUE} if it is too small
     95    */
     96   public static int saturatedCast(long value) {
     97     if (value > Integer.MAX_VALUE) {
     98       return Integer.MAX_VALUE;
     99     }
    100     if (value < Integer.MIN_VALUE) {
    101       return Integer.MIN_VALUE;
    102     }
    103     return (int) value;
    104   }
    105 
    106   /**
    107    * Compares the two specified {@code int} values. The sign of the value
    108    * returned is the same as that of {@code ((Integer) a).compareTo(b)}.
    109    *
    110    * @param a the first {@code int} to compare
    111    * @param b the second {@code int} to compare
    112    * @return a negative value if {@code a} is less than {@code b}; a positive
    113    *     value if {@code a} is greater than {@code b}; or zero if they are equal
    114    */
    115   public static int compare(int a, int b) {
    116     return (a < b) ? -1 : ((a > b) ? 1 : 0);
    117   }
    118 
    119   /**
    120    * Returns {@code true} if {@code target} is present as an element anywhere in
    121    * {@code array}.
    122    *
    123    * @param array an array of {@code int} values, possibly empty
    124    * @param target a primitive {@code int} value
    125    * @return {@code true} if {@code array[i] == target} for some value of {@code
    126    *     i}
    127    */
    128   public static boolean contains(int[] array, int target) {
    129     for (int value : array) {
    130       if (value == target) {
    131         return true;
    132       }
    133     }
    134     return false;
    135   }
    136 
    137   /**
    138    * Returns the index of the first appearance of the value {@code target} in
    139    * {@code array}.
    140    *
    141    * @param array an array of {@code int} values, possibly empty
    142    * @param target a primitive {@code int} value
    143    * @return the least index {@code i} for which {@code array[i] == target}, or
    144    *     {@code -1} if no such index exists.
    145    */
    146   public static int indexOf(int[] array, int target) {
    147     return indexOf(array, target, 0, array.length);
    148   }
    149 
    150   // TODO(kevinb): consider making this public
    151   private static int indexOf(
    152       int[] array, int target, int start, int end) {
    153     for (int i = start; i < end; i++) {
    154       if (array[i] == target) {
    155         return i;
    156       }
    157     }
    158     return -1;
    159   }
    160 
    161   /**
    162    * Returns the start position of the first occurrence of the specified {@code
    163    * target} within {@code array}, or {@code -1} if there is no such occurrence.
    164    *
    165    * <p>More formally, returns the lowest index {@code i} such that {@code
    166    * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
    167    * the same elements as {@code target}.
    168    *
    169    * @param array the array to search for the sequence {@code target}
    170    * @param target the array to search for as a sub-sequence of {@code array}
    171    */
    172   public static int indexOf(int[] array, int[] target) {
    173     checkNotNull(array, "array");
    174     checkNotNull(target, "target");
    175     if (target.length == 0) {
    176       return 0;
    177     }
    178 
    179     outer:
    180     for (int i = 0; i < array.length - target.length + 1; i++) {
    181       for (int j = 0; j < target.length; j++) {
    182         if (array[i + j] != target[j]) {
    183           continue outer;
    184         }
    185       }
    186       return i;
    187     }
    188     return -1;
    189   }
    190 
    191   /**
    192    * Returns the index of the last appearance of the value {@code target} in
    193    * {@code array}.
    194    *
    195    * @param array an array of {@code int} values, possibly empty
    196    * @param target a primitive {@code int} value
    197    * @return the greatest index {@code i} for which {@code array[i] == target},
    198    *     or {@code -1} if no such index exists.
    199    */
    200   public static int lastIndexOf(int[] array, int target) {
    201     return lastIndexOf(array, target, 0, array.length);
    202   }
    203 
    204   // TODO(kevinb): consider making this public
    205   private static int lastIndexOf(
    206       int[] array, int target, int start, int end) {
    207     for (int i = end - 1; i >= start; i--) {
    208       if (array[i] == target) {
    209         return i;
    210       }
    211     }
    212     return -1;
    213   }
    214 
    215   /**
    216    * Returns the least value present in {@code array}.
    217    *
    218    * @param array a <i>nonempty</i> array of {@code int} values
    219    * @return the value present in {@code array} that is less than or equal to
    220    *     every other value in the array
    221    * @throws IllegalArgumentException if {@code array} is empty
    222    */
    223   public static int min(int... array) {
    224     checkArgument(array.length > 0);
    225     int min = array[0];
    226     for (int i = 1; i < array.length; i++) {
    227       if (array[i] < min) {
    228         min = array[i];
    229       }
    230     }
    231     return min;
    232   }
    233 
    234   /**
    235    * Returns the greatest value present in {@code array}.
    236    *
    237    * @param array a <i>nonempty</i> array of {@code int} values
    238    * @return the value present in {@code array} that is greater than or equal to
    239    *     every other value in the array
    240    * @throws IllegalArgumentException if {@code array} is empty
    241    */
    242   public static int max(int... array) {
    243     checkArgument(array.length > 0);
    244     int max = array[0];
    245     for (int i = 1; i < array.length; i++) {
    246       if (array[i] > max) {
    247         max = array[i];
    248       }
    249     }
    250     return max;
    251   }
    252 
    253   /**
    254    * Returns the values from each provided array combined into a single array.
    255    * For example, {@code concat(new int[] {a, b}, new int[] {}, new
    256    * int[] {c}} returns the array {@code {a, b, c}}.
    257    *
    258    * @param arrays zero or more {@code int} arrays
    259    * @return a single array containing all the values from the source arrays, in
    260    *     order
    261    */
    262   public static int[] concat(int[]... arrays) {
    263     int length = 0;
    264     for (int[] array : arrays) {
    265       length += array.length;
    266     }
    267     int[] result = new int[length];
    268     int pos = 0;
    269     for (int[] array : arrays) {
    270       System.arraycopy(array, 0, result, pos, array.length);
    271       pos += array.length;
    272     }
    273     return result;
    274   }
    275 
    276   /**
    277    * Returns a big-endian representation of {@code value} in a 4-element byte
    278    * array; equivalent to {@code ByteBuffer.allocate(4).putInt(value).array()}.
    279    * For example, the input value {@code 0x12131415} would yield the byte array
    280    * {@code {0x12, 0x13, 0x14, 0x15}}.
    281    *
    282    * <p>If you need to convert and concatenate several values (possibly even of
    283    * different types), use a shared {@link java.nio.ByteBuffer} instance, or use
    284    * {@link com.google.common.io.ByteStreams#newDataOutput()} to get a growable
    285    * buffer.
    286    */
    287   @GwtIncompatible("doesn't work")
    288   public static byte[] toByteArray(int value) {
    289     return new byte[] {
    290         (byte) (value >> 24),
    291         (byte) (value >> 16),
    292         (byte) (value >> 8),
    293         (byte) value};
    294   }
    295 
    296   /**
    297    * Returns the {@code int} value whose big-endian representation is stored in
    298    * the first 4 bytes of {@code bytes}; equivalent to {@code
    299    * ByteBuffer.wrap(bytes).getInt()}. For example, the input byte array {@code
    300    * {0x12, 0x13, 0x14, 0x15, 0x33}} would yield the {@code int} value {@code
    301    * 0x12131415}.
    302    *
    303    * <p>Arguably, it's preferable to use {@link java.nio.ByteBuffer}; that
    304    * library exposes much more flexibility at little cost in readability.
    305    *
    306    * @throws IllegalArgumentException if {@code bytes} has fewer than 4 elements
    307    */
    308   @GwtIncompatible("doesn't work")
    309   public static int fromByteArray(byte[] bytes) {
    310     checkArgument(bytes.length >= BYTES,
    311         "array too small: %s < %s", bytes.length, BYTES);
    312     return fromBytes(bytes[0], bytes[1], bytes[2], bytes[3]);
    313   }
    314 
    315   /**
    316    * Returns the {@code int} value whose byte representation is the given 4
    317    * bytes, in big-endian order; equivalent to {@code Ints.fromByteArray(new
    318    * byte[] {b1, b2, b3, b4})}.
    319    *
    320    * @since 7.0
    321    */
    322   @GwtIncompatible("doesn't work")
    323   public static int fromBytes(byte b1, byte b2, byte b3, byte b4) {
    324     return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | (b4 & 0xFF);
    325   }
    326 
    327   /**
    328    * Returns an array containing the same values as {@code array}, but
    329    * guaranteed to be of a specified minimum length. If {@code array} already
    330    * has a length of at least {@code minLength}, it is returned directly.
    331    * Otherwise, a new array of size {@code minLength + padding} is returned,
    332    * containing the values of {@code array}, and zeroes in the remaining places.
    333    *
    334    * @param array the source array
    335    * @param minLength the minimum length the returned array must guarantee
    336    * @param padding an extra amount to "grow" the array by if growth is
    337    *     necessary
    338    * @throws IllegalArgumentException if {@code minLength} or {@code padding} is
    339    *     negative
    340    * @return an array containing the values of {@code array}, with guaranteed
    341    *     minimum length {@code minLength}
    342    */
    343   public static int[] ensureCapacity(
    344       int[] array, int minLength, int padding) {
    345     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
    346     checkArgument(padding >= 0, "Invalid padding: %s", padding);
    347     return (array.length < minLength)
    348         ? copyOf(array, minLength + padding)
    349         : array;
    350   }
    351 
    352   // Arrays.copyOf() requires Java 6
    353   private static int[] copyOf(int[] original, int length) {
    354     int[] copy = new int[length];
    355     System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
    356     return copy;
    357   }
    358 
    359   /**
    360    * Returns a string containing the supplied {@code int} values separated
    361    * by {@code separator}. For example, {@code join("-", 1, 2, 3)} returns
    362    * the string {@code "1-2-3"}.
    363    *
    364    * @param separator the text that should appear between consecutive values in
    365    *     the resulting string (but not at the start or end)
    366    * @param array an array of {@code int} values, possibly empty
    367    */
    368   public static String join(String separator, int... array) {
    369     checkNotNull(separator);
    370     if (array.length == 0) {
    371       return "";
    372     }
    373 
    374     // For pre-sizing a builder, just get the right order of magnitude
    375     StringBuilder builder = new StringBuilder(array.length * 5);
    376     builder.append(array[0]);
    377     for (int i = 1; i < array.length; i++) {
    378       builder.append(separator).append(array[i]);
    379     }
    380     return builder.toString();
    381   }
    382 
    383   /**
    384    * Returns a comparator that compares two {@code int} arrays
    385    * lexicographically. That is, it compares, using {@link
    386    * #compare(int, int)}), the first pair of values that follow any
    387    * common prefix, or when one array is a prefix of the other, treats the
    388    * shorter array as the lesser. For example, {@code [] < [1] < [1, 2] < [2]}.
    389    *
    390    * <p>The returned comparator is inconsistent with {@link
    391    * Object#equals(Object)} (since arrays support only identity equality), but
    392    * it is consistent with {@link Arrays#equals(int[], int[])}.
    393    *
    394    * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
    395    *     Lexicographical order article at Wikipedia</a>
    396    * @since 2.0
    397    */
    398   public static Comparator<int[]> lexicographicalComparator() {
    399     return LexicographicalComparator.INSTANCE;
    400   }
    401 
    402   private enum LexicographicalComparator implements Comparator<int[]> {
    403     INSTANCE;
    404 
    405     @Override
    406     public int compare(int[] left, int[] right) {
    407       int minLength = Math.min(left.length, right.length);
    408       for (int i = 0; i < minLength; i++) {
    409         int result = Ints.compare(left[i], right[i]);
    410         if (result != 0) {
    411           return result;
    412         }
    413       }
    414       return left.length - right.length;
    415     }
    416   }
    417 
    418   /**
    419    * Copies a collection of {@code Integer} instances into a new array of
    420    * primitive {@code int} values.
    421    *
    422    * <p>Elements are copied from the argument collection as if by {@code
    423    * collection.toArray()}.  Calling this method is as thread-safe as calling
    424    * that method.
    425    *
    426    * @param collection a collection of {@code Integer} objects
    427    * @return an array containing the same values as {@code collection}, in the
    428    *     same order, converted to primitives
    429    * @throws NullPointerException if {@code collection} or any of its elements
    430    *     is null
    431    */
    432   public static int[] toArray(Collection<Integer> collection) {
    433     if (collection instanceof IntArrayAsList) {
    434       return ((IntArrayAsList) collection).toIntArray();
    435     }
    436 
    437     Object[] boxedArray = collection.toArray();
    438     int len = boxedArray.length;
    439     int[] array = new int[len];
    440     for (int i = 0; i < len; i++) {
    441       // checkNotNull for GWT (do not optimize)
    442       array[i] = (Integer) checkNotNull(boxedArray[i]);
    443     }
    444     return array;
    445   }
    446 
    447   /**
    448    * Returns a fixed-size list backed by the specified array, similar to {@link
    449    * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)},
    450    * but any attempt to set a value to {@code null} will result in a {@link
    451    * NullPointerException}.
    452    *
    453    * <p>The returned list maintains the values, but not the identities, of
    454    * {@code Integer} objects written to or read from it.  For example, whether
    455    * {@code list.get(0) == list.get(0)} is true for the returned list is
    456    * unspecified.
    457    *
    458    * @param backingArray the array to back the list
    459    * @return a list view of the array
    460    */
    461   public static List<Integer> asList(int... backingArray) {
    462     if (backingArray.length == 0) {
    463       return Collections.emptyList();
    464     }
    465     return new IntArrayAsList(backingArray);
    466   }
    467 
    468   @GwtCompatible
    469   private static class IntArrayAsList extends AbstractList<Integer>
    470       implements RandomAccess, Serializable {
    471     final int[] array;
    472     final int start;
    473     final int end;
    474 
    475     IntArrayAsList(int[] array) {
    476       this(array, 0, array.length);
    477     }
    478 
    479     IntArrayAsList(int[] array, int start, int end) {
    480       this.array = array;
    481       this.start = start;
    482       this.end = end;
    483     }
    484 
    485     @Override public int size() {
    486       return end - start;
    487     }
    488 
    489     @Override public boolean isEmpty() {
    490       return false;
    491     }
    492 
    493     @Override public Integer get(int index) {
    494       checkElementIndex(index, size());
    495       return array[start + index];
    496     }
    497 
    498     @Override public boolean contains(Object target) {
    499       // Overridden to prevent a ton of boxing
    500       return (target instanceof Integer)
    501           && Ints.indexOf(array, (Integer) target, start, end) != -1;
    502     }
    503 
    504     @Override public int indexOf(Object target) {
    505       // Overridden to prevent a ton of boxing
    506       if (target instanceof Integer) {
    507         int i = Ints.indexOf(array, (Integer) target, start, end);
    508         if (i >= 0) {
    509           return i - start;
    510         }
    511       }
    512       return -1;
    513     }
    514 
    515     @Override public int lastIndexOf(Object target) {
    516       // Overridden to prevent a ton of boxing
    517       if (target instanceof Integer) {
    518         int i = Ints.lastIndexOf(array, (Integer) target, start, end);
    519         if (i >= 0) {
    520           return i - start;
    521         }
    522       }
    523       return -1;
    524     }
    525 
    526     @Override public Integer set(int index, Integer element) {
    527       checkElementIndex(index, size());
    528       int oldValue = array[start + index];
    529       array[start + index] = checkNotNull(element);  // checkNotNull for GWT (do not optimize)
    530       return oldValue;
    531     }
    532 
    533     @Override public List<Integer> subList(int fromIndex, int toIndex) {
    534       int size = size();
    535       checkPositionIndexes(fromIndex, toIndex, size);
    536       if (fromIndex == toIndex) {
    537         return Collections.emptyList();
    538       }
    539       return new IntArrayAsList(array, start + fromIndex, start + toIndex);
    540     }
    541 
    542     @Override public boolean equals(Object object) {
    543       if (object == this) {
    544         return true;
    545       }
    546       if (object instanceof IntArrayAsList) {
    547         IntArrayAsList that = (IntArrayAsList) object;
    548         int size = size();
    549         if (that.size() != size) {
    550           return false;
    551         }
    552         for (int i = 0; i < size; i++) {
    553           if (array[start + i] != that.array[that.start + i]) {
    554             return false;
    555           }
    556         }
    557         return true;
    558       }
    559       return super.equals(object);
    560     }
    561 
    562     @Override public int hashCode() {
    563       int result = 1;
    564       for (int i = start; i < end; i++) {
    565         result = 31 * result + Ints.hashCode(array[i]);
    566       }
    567       return result;
    568     }
    569 
    570     @Override public String toString() {
    571       StringBuilder builder = new StringBuilder(size() * 5);
    572       builder.append('[').append(array[start]);
    573       for (int i = start + 1; i < end; i++) {
    574         builder.append(", ").append(array[i]);
    575       }
    576       return builder.append(']').toString();
    577     }
    578 
    579     int[] toIntArray() {
    580       // Arrays.copyOfRange() requires Java 6
    581       int size = size();
    582       int[] result = new int[size];
    583       System.arraycopy(array, start, result, 0, size);
    584       return result;
    585     }
    586 
    587     private static final long serialVersionUID = 0;
    588   }
    589 
    590   /**
    591    * Parses the specified string as a signed decimal integer value. The ASCII
    592    * character {@code '-'} (<code>'&#92;u002D'</code>) is recognized as the
    593    * minus sign.
    594    *
    595    * <p>Unlike {@link Integer#parseInt(String)}, this method returns
    596    * {@code null} instead of throwing an exception if parsing fails.
    597    *
    598    * <p>Note that strings prefixed with ASCII {@code '+'} are rejected, even
    599    * under JDK 7, despite the change to {@link Integer#parseInt(String)} for
    600    * that version.
    601    *
    602    * @param string the string representation of an integer value
    603    * @return the integer value represented by {@code string}, or {@code null} if
    604    *     {@code string} has a length of zero or cannot be parsed as an integer
    605    *     value
    606    * @since 11.0
    607    */
    608   @Beta
    609   @CheckForNull
    610   @GwtIncompatible("TODO")
    611   public static Integer tryParse(String string) {
    612     return AndroidInteger.tryParse(string, 10);
    613   }
    614 }
    615