001/*
002 * Copyright (C) 2008 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.primitives;
016
017import static com.google.common.base.Preconditions.checkArgument;
018import static com.google.common.base.Preconditions.checkElementIndex;
019import static com.google.common.base.Preconditions.checkNotNull;
020import static com.google.common.base.Preconditions.checkPositionIndexes;
021
022import com.google.common.annotations.Beta;
023import com.google.common.annotations.GwtCompatible;
024import java.io.Serializable;
025import java.util.AbstractList;
026import java.util.Arrays;
027import java.util.Collection;
028import java.util.Collections;
029import java.util.Comparator;
030import java.util.List;
031import java.util.RandomAccess;
032import javax.annotation.Nullable;
033
034/**
035 * Static utility methods pertaining to {@code boolean} primitives, that are not already found in
036 * either {@link Boolean} or {@link Arrays}.
037 *
038 * <p>See the Guava User Guide article on
039 * <a href="https://github.com/google/guava/wiki/PrimitivesExplained">primitive utilities</a>.
040 *
041 * @author Kevin Bourrillion
042 * @since 1.0
043 */
044@GwtCompatible
045public final class Booleans {
046  private Booleans() {}
047
048  /**
049   * Comparators for {@code Boolean} values.
050   */
051  private enum BooleanComparator implements Comparator<Boolean> {
052    TRUE_FIRST(1, "Booleans.trueFirst()"),
053    FALSE_FIRST(-1, "Booleans.falseFirst()");
054
055    private final int trueValue;
056    private final String toString;
057
058    BooleanComparator(int trueValue, String toString) {
059      this.trueValue = trueValue;
060      this.toString = toString;
061    }
062
063    @Override
064    public int compare(Boolean a, Boolean b) {
065      int aVal = a ? trueValue : 0;
066      int bVal = b ? trueValue : 0;
067      return bVal - aVal;
068    }
069
070    @Override
071    public String toString() {
072      return toString;
073    }
074  }
075
076  /**
077   * Returns a {@code Comparator<Boolean>} that sorts {@code true} before {@code false}.
078   *
079   * <p>This is particularly useful in Java 8+ in combination with {@code Comparators.comparing},
080   * e.g. {@code Comparators.comparing(Foo::hasBar, trueFirst())}.
081   *
082   * @since 21.0
083   */
084  @Beta
085  public static Comparator<Boolean> trueFirst() {
086    return BooleanComparator.TRUE_FIRST;
087  }
088
089  /**
090   * Returns a {@code Comparator<Boolean>} that sorts {@code false} before {@code true}.
091   *
092   * <p>This is particularly useful in Java 8+ in combination with {@code Comparators.comparing},
093   * e.g. {@code Comparators.comparing(Foo::hasBar, falseFirst())}.
094   *
095   * @since 21.0
096   */
097  @Beta
098  public static Comparator<Boolean> falseFirst() {
099    return BooleanComparator.FALSE_FIRST;
100  }
101
102  /**
103   * Returns a hash code for {@code value}; equal to the result of invoking
104   * {@code ((Boolean) value).hashCode()}.
105   *
106   * <p><b>Java 8 users:</b> use {@link Boolean#hashCode(boolean)} instead.
107   *
108   * @param value a primitive {@code boolean} value
109   * @return a hash code for the value
110   */
111  public static int hashCode(boolean value) {
112    return value ? 1231 : 1237;
113  }
114
115  /**
116   * Compares the two specified {@code boolean} values in the standard way ({@code false} is
117   * considered less than {@code true}). The sign of the value returned is the same as that of
118   * {@code ((Boolean) a).compareTo(b)}.
119   *
120   * <p><b>Note for Java 7 and later:</b> this method should be treated as deprecated; use the
121   * equivalent {@link Boolean#compare} method instead.
122   *
123   * @param a the first {@code boolean} to compare
124   * @param b the second {@code boolean} to compare
125   * @return a positive number if only {@code a} is {@code true}, a negative number if only
126   *     {@code b} is true, or zero if {@code a == b}
127   */
128  public static int compare(boolean a, boolean b) {
129    return (a == b) ? 0 : (a ? 1 : -1);
130  }
131
132  /**
133   * Returns {@code true} if {@code target} is present as an element anywhere in {@code array}.
134   *
135   * <p><b>Note:</b> consider representing the array as a {@link java.util.BitSet} instead,
136   * replacing {@code Booleans.contains(array, true)} with {@code !bitSet.isEmpty()} and
137   * {@code Booleans.contains(array, false)} with {@code bitSet.nextClearBit(0) == sizeOfBitSet}.
138   *
139   * @param array an array of {@code boolean} values, possibly empty
140   * @param target a primitive {@code boolean} value
141   * @return {@code true} if {@code array[i] == target} for some value of {@code
142   *     i}
143   */
144  public static boolean contains(boolean[] array, boolean target) {
145    for (boolean value : array) {
146      if (value == target) {
147        return true;
148      }
149    }
150    return false;
151  }
152
153  /**
154   * Returns the index of the first appearance of the value {@code target} in {@code array}.
155   *
156   * <p><b>Note:</b> consider representing the array as a {@link java.util.BitSet} instead, and
157   * using {@link java.util.BitSet#nextSetBit(int)} or {@link java.util.BitSet#nextClearBit(int)}.
158   *
159   * @param array an array of {@code boolean} values, possibly empty
160   * @param target a primitive {@code boolean} value
161   * @return the least index {@code i} for which {@code array[i] == target}, or {@code -1} if no
162   *     such index exists.
163   */
164  public static int indexOf(boolean[] array, boolean target) {
165    return indexOf(array, target, 0, array.length);
166  }
167
168  // TODO(kevinb): consider making this public
169  private static int indexOf(boolean[] array, boolean target, int start, int end) {
170    for (int i = start; i < end; i++) {
171      if (array[i] == target) {
172        return i;
173      }
174    }
175    return -1;
176  }
177
178  /**
179   * Returns the start position of the first occurrence of the specified {@code
180   * target} within {@code array}, or {@code -1} if there is no such occurrence.
181   *
182   * <p>More formally, returns the lowest index {@code i} such that {@code
183   * Arrays.copyOfRange(array, i, i + target.length)} contains exactly the same elements as
184   * {@code target}.
185   *
186   * @param array the array to search for the sequence {@code target}
187   * @param target the array to search for as a sub-sequence of {@code array}
188   */
189  public static int indexOf(boolean[] array, boolean[] target) {
190    checkNotNull(array, "array");
191    checkNotNull(target, "target");
192    if (target.length == 0) {
193      return 0;
194    }
195
196    outer:
197    for (int i = 0; i < array.length - target.length + 1; i++) {
198      for (int j = 0; j < target.length; j++) {
199        if (array[i + j] != target[j]) {
200          continue outer;
201        }
202      }
203      return i;
204    }
205    return -1;
206  }
207
208  /**
209   * Returns the index of the last appearance of the value {@code target} in {@code array}.
210   *
211   * @param array an array of {@code boolean} values, possibly empty
212   * @param target a primitive {@code boolean} value
213   * @return the greatest index {@code i} for which {@code array[i] == target}, or {@code -1} if no
214   *     such index exists.
215   */
216  public static int lastIndexOf(boolean[] array, boolean target) {
217    return lastIndexOf(array, target, 0, array.length);
218  }
219
220  // TODO(kevinb): consider making this public
221  private static int lastIndexOf(boolean[] array, boolean target, int start, int end) {
222    for (int i = end - 1; i >= start; i--) {
223      if (array[i] == target) {
224        return i;
225      }
226    }
227    return -1;
228  }
229
230  /**
231   * Returns the values from each provided array combined into a single array. For example,
232   * {@code concat(new boolean[] {a, b}, new boolean[] {}, new boolean[] {c}} returns the array
233   * {@code {a, b, c}}.
234   *
235   * @param arrays zero or more {@code boolean} arrays
236   * @return a single array containing all the values from the source arrays, in order
237   */
238  public static boolean[] concat(boolean[]... arrays) {
239    int length = 0;
240    for (boolean[] array : arrays) {
241      length += array.length;
242    }
243    boolean[] result = new boolean[length];
244    int pos = 0;
245    for (boolean[] array : arrays) {
246      System.arraycopy(array, 0, result, pos, array.length);
247      pos += array.length;
248    }
249    return result;
250  }
251
252  /**
253   * Returns an array containing the same values as {@code array}, but guaranteed to be of a
254   * specified minimum length. If {@code array} already has a length of at least {@code minLength},
255   * it is returned directly. Otherwise, a new array of size {@code minLength + padding} is
256   * returned, containing the values of {@code array}, and zeroes in the remaining places.
257   *
258   * @param array the source array
259   * @param minLength the minimum length the returned array must guarantee
260   * @param padding an extra amount to "grow" the array by if growth is necessary
261   * @throws IllegalArgumentException if {@code minLength} or {@code padding} is negative
262   * @return an array containing the values of {@code array}, with guaranteed minimum length
263   *     {@code minLength}
264   */
265  public static boolean[] ensureCapacity(boolean[] array, int minLength, int padding) {
266    checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
267    checkArgument(padding >= 0, "Invalid padding: %s", padding);
268    return (array.length < minLength) ? Arrays.copyOf(array, minLength + padding) : array;
269  }
270
271  /**
272   * Returns a string containing the supplied {@code boolean} values separated by {@code separator}.
273   * For example, {@code join("-", false, true, false)} returns the string
274   * {@code "false-true-false"}.
275   *
276   * @param separator the text that should appear between consecutive values in the resulting string
277   *     (but not at the start or end)
278   * @param array an array of {@code boolean} values, possibly empty
279   */
280  public static String join(String separator, boolean... array) {
281    checkNotNull(separator);
282    if (array.length == 0) {
283      return "";
284    }
285
286    // For pre-sizing a builder, just get the right order of magnitude
287    StringBuilder builder = new StringBuilder(array.length * 7);
288    builder.append(array[0]);
289    for (int i = 1; i < array.length; i++) {
290      builder.append(separator).append(array[i]);
291    }
292    return builder.toString();
293  }
294
295  /**
296   * Returns a comparator that compares two {@code boolean} arrays <a
297   * href="http://en.wikipedia.org/wiki/Lexicographical_order">lexicographically</a>. That is, it
298   * compares, using {@link #compare(boolean, boolean)}), the first pair of values that follow any
299   * common prefix, or when one array is a prefix of the other, treats the shorter array as the
300   * lesser. For example, {@code [] < [false] < [false, true] < [true]}.
301   *
302   * <p>The returned comparator is inconsistent with {@link Object#equals(Object)} (since arrays
303   * support only identity equality), but it is consistent with
304   * {@link Arrays#equals(boolean[], boolean[])}.
305   *
306   * @since 2.0
307   */
308  public static Comparator<boolean[]> lexicographicalComparator() {
309    return LexicographicalComparator.INSTANCE;
310  }
311
312  private enum LexicographicalComparator implements Comparator<boolean[]> {
313    INSTANCE;
314
315    @Override
316    public int compare(boolean[] left, boolean[] right) {
317      int minLength = Math.min(left.length, right.length);
318      for (int i = 0; i < minLength; i++) {
319        int result = Booleans.compare(left[i], right[i]);
320        if (result != 0) {
321          return result;
322        }
323      }
324      return left.length - right.length;
325    }
326
327    @Override
328    public String toString() {
329      return "Booleans.lexicographicalComparator()";
330    }
331  }
332
333  /**
334   * Copies a collection of {@code Boolean} instances into a new array of primitive {@code boolean}
335   * values.
336   *
337   * <p>Elements are copied from the argument collection as if by {@code
338   * collection.toArray()}. Calling this method is as thread-safe as calling that method.
339   *
340   * <p><b>Note:</b> consider representing the collection as a {@link java.util.BitSet} instead.
341   *
342   * @param collection a collection of {@code Boolean} objects
343   * @return an array containing the same values as {@code collection}, in the same order, converted
344   *     to primitives
345   * @throws NullPointerException if {@code collection} or any of its elements is null
346   */
347  public static boolean[] toArray(Collection<Boolean> collection) {
348    if (collection instanceof BooleanArrayAsList) {
349      return ((BooleanArrayAsList) collection).toBooleanArray();
350    }
351
352    Object[] boxedArray = collection.toArray();
353    int len = boxedArray.length;
354    boolean[] array = new boolean[len];
355    for (int i = 0; i < len; i++) {
356      // checkNotNull for GWT (do not optimize)
357      array[i] = (Boolean) checkNotNull(boxedArray[i]);
358    }
359    return array;
360  }
361
362  /**
363   * Returns a fixed-size list backed by the specified array, similar to
364   * {@link Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)}, but any
365   * attempt to set a value to {@code null} will result in a {@link NullPointerException}.
366   *
367   * <p>The returned list maintains the values, but not the identities, of {@code Boolean} objects
368   * written to or read from it. For example, whether {@code list.get(0) == list.get(0)} is true for
369   * the returned list is unspecified.
370   *
371   * @param backingArray the array to back the list
372   * @return a list view of the array
373   */
374  public static List<Boolean> asList(boolean... backingArray) {
375    if (backingArray.length == 0) {
376      return Collections.emptyList();
377    }
378    return new BooleanArrayAsList(backingArray);
379  }
380
381  @GwtCompatible
382  private static class BooleanArrayAsList extends AbstractList<Boolean>
383      implements RandomAccess, Serializable {
384    final boolean[] array;
385    final int start;
386    final int end;
387
388    BooleanArrayAsList(boolean[] array) {
389      this(array, 0, array.length);
390    }
391
392    BooleanArrayAsList(boolean[] array, int start, int end) {
393      this.array = array;
394      this.start = start;
395      this.end = end;
396    }
397
398    @Override
399    public int size() {
400      return end - start;
401    }
402
403    @Override
404    public boolean isEmpty() {
405      return false;
406    }
407
408    @Override
409    public Boolean get(int index) {
410      checkElementIndex(index, size());
411      return array[start + index];
412    }
413
414    @Override
415    public boolean contains(Object target) {
416      // Overridden to prevent a ton of boxing
417      return (target instanceof Boolean)
418          && Booleans.indexOf(array, (Boolean) target, start, end) != -1;
419    }
420
421    @Override
422    public int indexOf(Object target) {
423      // Overridden to prevent a ton of boxing
424      if (target instanceof Boolean) {
425        int i = Booleans.indexOf(array, (Boolean) target, start, end);
426        if (i >= 0) {
427          return i - start;
428        }
429      }
430      return -1;
431    }
432
433    @Override
434    public int lastIndexOf(Object target) {
435      // Overridden to prevent a ton of boxing
436      if (target instanceof Boolean) {
437        int i = Booleans.lastIndexOf(array, (Boolean) target, start, end);
438        if (i >= 0) {
439          return i - start;
440        }
441      }
442      return -1;
443    }
444
445    @Override
446    public Boolean set(int index, Boolean element) {
447      checkElementIndex(index, size());
448      boolean oldValue = array[start + index];
449      // checkNotNull for GWT (do not optimize)
450      array[start + index] = checkNotNull(element);
451      return oldValue;
452    }
453
454    @Override
455    public List<Boolean> subList(int fromIndex, int toIndex) {
456      int size = size();
457      checkPositionIndexes(fromIndex, toIndex, size);
458      if (fromIndex == toIndex) {
459        return Collections.emptyList();
460      }
461      return new BooleanArrayAsList(array, start + fromIndex, start + toIndex);
462    }
463
464    @Override
465    public boolean equals(@Nullable Object object) {
466      if (object == this) {
467        return true;
468      }
469      if (object instanceof BooleanArrayAsList) {
470        BooleanArrayAsList that = (BooleanArrayAsList) object;
471        int size = size();
472        if (that.size() != size) {
473          return false;
474        }
475        for (int i = 0; i < size; i++) {
476          if (array[start + i] != that.array[that.start + i]) {
477            return false;
478          }
479        }
480        return true;
481      }
482      return super.equals(object);
483    }
484
485    @Override
486    public int hashCode() {
487      int result = 1;
488      for (int i = start; i < end; i++) {
489        result = 31 * result + Booleans.hashCode(array[i]);
490      }
491      return result;
492    }
493
494    @Override
495    public String toString() {
496      StringBuilder builder = new StringBuilder(size() * 7);
497      builder.append(array[start] ? "[true" : "[false");
498      for (int i = start + 1; i < end; i++) {
499        builder.append(array[i] ? ", true" : ", false");
500      }
501      return builder.append(']').toString();
502    }
503
504    boolean[] toBooleanArray() {
505      return Arrays.copyOfRange(array, start, end);
506    }
507
508    private static final long serialVersionUID = 0;
509  }
510
511  /**
512   * Returns the number of {@code values} that are {@code true}.
513   *
514   * @since 16.0
515   */
516  @Beta
517  public static int countTrue(boolean... values) {
518    int count = 0;
519    for (boolean value : values) {
520      if (value) {
521        count++;
522      }
523    }
524    return count;
525  }
526}