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