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