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