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