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