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