001/* 002 * Copyright (C) 2002-2015 Sebastiano Vigna 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package regexodus.ds; 017 018import java.util.Arrays; 019import java.util.Collection; 020import java.util.Iterator; 021import java.util.List; 022import java.util.ListIterator; 023import java.util.NoSuchElementException; 024import java.util.RandomAccess; 025 026/** 027 * A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing. 028 * <p> 029 * <P>This class implements a lightweight, fast, open, optimized, reuse-oriented version of array-based lists. Instances of this class represent a list with an array that is enlarged as needed when 030 * new entries are created (by doubling its current length), but is <em>never</em> made smaller (even on a {@link #clear()}). A family of {@linkplain #trim() trimming methods} lets you control the size 031 * of the backing array; this is particularly useful if you reuse instances of this class. Range checks are equivalent to those of {@link java.util}'s classes, but they are delayed as much as 032 * possible. The backing array is exposed by the {@link #elements()} method. 033 * <p> 034 * <p>This class implements the bulk methods <code>removeElements()</code>, <code>addElements()</code> and <code>getElements()</code> using high-performance system calls (e.g., 035 * {@link System#arraycopy(Object, int, Object, int, int) System.arraycopy()} instead of expensive loops. 036 * 037 * @see java.util.ArrayList 038 */ 039public class CharArrayList implements RandomAccess, Cloneable, java.io.Serializable, List<Character>, Comparable<List<? extends Character>> { 040 private static final long serialVersionUID = -7046029254386353130L; 041 /** 042 * The initial default capacity of an array list. 043 */ 044 private final static int DEFAULT_INITIAL_CAPACITY = 16; 045 /** 046 * The backing array. 047 */ 048 private transient char[] a; 049 /** 050 * The current actual size of the list (never greater than the backing-array length). 051 */ 052 private int size; 053 //private static final boolean ASSERTS = false; 054 055 /** 056 * Creates a new array list using a given array. 057 * <p> 058 * <P>This constructor is only meant to be used by the wrapping methods. 059 * 060 * @param a the array that will be used to back this array list. 061 */ 062 protected CharArrayList(final char a[], boolean dummy) { 063 this.a = a; 064 } 065 066 /** 067 * Creates a new array list with given capacity. 068 * 069 * @param capacity the initial capacity of the array list (may be 0). 070 */ 071 072 public CharArrayList(final int capacity) { 073 if (capacity < 0) throw new IllegalArgumentException("Initial capacity (" + capacity + ") is negative"); 074 a = new char[capacity]; 075 } 076 077 /** 078 * Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity. 079 */ 080 private CharArrayList() { 081 this(DEFAULT_INITIAL_CAPACITY); 082 } 083 084 /** 085 * Creates a new array list and fills it with a given type-specific list. 086 * 087 * @param l a type-specific list that will be used to fill the array list. 088 */ 089 public CharArrayList(final CharArrayList l) { 090 this(l.size()); 091 l.getElements(0, a, 0, size = l.size()); 092 } 093 094 /** 095 * Creates a new array list and fills it with the elements of a given array or vararg. 096 * 097 * @param a an array or vararg whose elements will be used to fill the array list. 098 */ 099 private CharArrayList(final char... a) { 100 this(a, 0, a.length); 101 } 102 103 /** 104 * Creates a new array list and fills it with the elements of a given String. 105 * 106 * @param s a String whose char elements will be used to fill the array list. 107 */ 108 public CharArrayList(final String s) { this(s.toCharArray());} 109 /** 110 * Creates a new array list and fills it with the elements of a given array. 111 * 112 * @param a an array whose elements will be used to fill the array list. 113 * @param offset the first element to use. 114 * @param length the number of elements to use. 115 */ 116 private CharArrayList(final char a[], final int offset, final int length) { 117 this(length); 118 System.arraycopy(a, offset, this.a, 0, length); 119 size = length; 120 } 121 122 /** 123 * Creates a new array list and fills it with the elements returned by an iterator.. 124 * 125 * @param i an iterator whose returned elements will fill the array list. 126 */ 127 public CharArrayList(final Iterator<? extends Character> i) { 128 this(); 129 while (i.hasNext()) 130 this.add(i.next()); 131 } 132 133 /** 134 * Returns the backing array of this list. 135 * 136 * @return the backing array. 137 */ 138 public char[] elements() { 139 return a; 140 } 141 142 /** 143 * Wraps a given array into an array list of given size. 144 * <p> 145 * <P>Note it is guaranteed that the type of the array returned by {@link #elements()} will be the same (see the comments in the class documentation). 146 * 147 * @param a an array to wrap. 148 * @param length the length of the resulting array list. 149 * @return a new array list of the given size, wrapping the given array. 150 */ 151 private static CharArrayList wrap(final char a[], final int length) { 152 if (length > a.length) 153 throw new IllegalArgumentException("The specified length (" + length + ") is greater than the array size (" + a.length + ")"); 154 final CharArrayList l = new CharArrayList(a, false); 155 l.size = length; 156 return l; 157 } 158 159 /** 160 * Wraps a given array into an array list. 161 * <p> 162 * <P>Note it is guaranteed that the type of the array returned by {@link #elements()} will be the same (see the comments in the class documentation). 163 * 164 * @param a an array to wrap. 165 * @return a new array list wrapping the given array. 166 */ 167 public static CharArrayList wrap(final char a[]) { 168 return wrap(a, a.length); 169 } 170 171 /** 172 * Ensures that this array list can contain the given number of entries without resizing. 173 * 174 * @param capacity the new minimum capacity for this array list. 175 */ 176 177 private void ensureCapacity(final int capacity) { 178 a = CharArrays.ensureCapacity(a, capacity, size); 179 //if (ASSERTS) assert size <= a.length; 180 } 181 182 /** 183 * Grows this array list, ensuring that it can contain the given number of entries without resizing, and in case enlarging it at least by a factor of two. 184 * 185 * @param capacity the new minimum capacity for this array list. 186 */ 187 188 private void grow(final int capacity) { 189 a = CharArrays.grow(a, capacity, size); 190 //if (ASSERTS) assert size <= a.length; 191 } 192 193 private void add(final int index, final char k) { 194 ensureIndex(index); 195 grow(size + 1); 196 if (index != size) System.arraycopy(a, index, a, index + 1, size - index); 197 a[index] = k; 198 size++; 199 //if (ASSERTS) assert size <= a.length; 200 } 201 202 private boolean add(final char k) { 203 grow(size + 1); 204 a[size++] = k; 205 //if (ASSERTS) assert size <= a.length; 206 return true; 207 } 208 public boolean add(final int k) { 209 grow(size + 1); 210 a[size++] = (char)k; 211 //if (ASSERTS) assert size <= a.length; 212 return true; 213 } 214 215 public char getChar(final int index) { 216 if (index >= size) 217 throw new IndexOutOfBoundsException("Index (" + index + ") is greater than or equal to list size (" + size + ")"); 218 return a[index]; 219 } 220 221 public int getCodePoint(final int index) { 222 if (index >= size) 223 throw new IndexOutOfBoundsException("Index (" + index + ") is greater than or equal to list size (" + size + ")"); 224 return a[index]; 225 } 226 227 private int indexOf(final char k) { 228 for (int i = 0; i < size; i++) 229 if (((k) == (a[i]))) return i; 230 return -1; 231 } 232 233 public int lastIndexOf(final char k) { 234 for (int i = size; i-- != 0; ) 235 if (((k) == (a[i]))) return i; 236 return -1; 237 } 238 239 private char removeChar(final int index) { 240 if (index >= size) 241 throw new IndexOutOfBoundsException("Index (" + index + ") is greater than or equal to list size (" + size + ")"); 242 final char old = a[index]; 243 size--; 244 if (index != size) System.arraycopy(a, index + 1, a, index, size - index); 245 //if (ASSERTS) assert size <= a.length; 246 return old; 247 } 248 249 private boolean rem(final char k) { 250 int index = indexOf(k); 251 if (index == -1) return false; 252 removeChar(index); 253 //if (ASSERTS) assert size <= a.length; 254 return true; 255 } 256 257 /** 258 * Delegates to the corresponding type-specific method. 259 * 260 * @deprecated Please use the corresponding type-specific method instead. 261 */ 262 @Deprecated 263 public Character set(final int index, final Character ok) { 264 return set(index, ok.charValue()); 265 } 266 267 /** 268 * Inserts the specified element at the specified position in this list 269 * (optional operation). Shifts the element currently at that position 270 * (if any) and any subsequent elements to the right (adds one to their 271 * indices). 272 * 273 * @param index index at which the specified element is to be inserted 274 * @param element element to be inserted 275 * @throws UnsupportedOperationException if the <tt>add</tt> operation 276 * is not supported by this list 277 * @throws ClassCastException if the class of the specified element 278 * prevents it from being added to this list 279 * @throws NullPointerException if the specified element is null and 280 * this list does not permit null elements 281 * @throws IllegalArgumentException if some property of the specified 282 * element prevents it from being added to this list 283 * @throws IndexOutOfBoundsException if the index is out of range 284 * (<tt>index < 0 || index > size()</tt>) 285 */ 286 @Override 287 public void add(int index, Character element) { 288 289 } 290 291 /** 292 * Removes the element at the specified position in this list (optional 293 * operation). Shifts any subsequent elements to the left (subtracts one 294 * from their indices). Returns the element that was removed from the 295 * list. 296 * 297 * @param index the index of the element to be removed 298 * @return the element previously at the specified position 299 * @throws UnsupportedOperationException if the <tt>remove</tt> operation 300 * is not supported by this list 301 * @throws IndexOutOfBoundsException if the index is out of range 302 * (<tt>index < 0 || index >= size()</tt>) 303 */ 304 @Override 305 public Character remove(int index) { 306 return null; 307 } 308 309 /** 310 * Returns the index of the first occurrence of the specified element 311 * in this list, or -1 if this list does not contain the element. 312 * More formally, returns the lowest index <tt>i</tt> such that 313 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, 314 * or -1 if there is no such index. 315 * 316 * @param o element to search for 317 * @return the index of the first occurrence of the specified element in 318 * this list, or -1 if this list does not contain the element 319 * @throws ClassCastException if the type of the specified element 320 * is incompatible with this list 321 * (<a href="Collection.html#optional-restrictions">optional</a>) 322 * @throws NullPointerException if the specified element is null and this 323 * list does not permit null elements 324 * (<a href="Collection.html#optional-restrictions">optional</a>) 325 */ 326 @Override 327 public int indexOf(Object o) { 328 return 0; 329 } 330 331 /** 332 * Returns the index of the last occurrence of the specified element 333 * in this list, or -1 if this list does not contain the element. 334 * More formally, returns the highest index <tt>i</tt> such that 335 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, 336 * or -1 if there is no such index. 337 * 338 * @param o element to search for 339 * @return the index of the last occurrence of the specified element in 340 * this list, or -1 if this list does not contain the element 341 * @throws ClassCastException if the type of the specified element 342 * is incompatible with this list 343 * (<a href="Collection.html#optional-restrictions">optional</a>) 344 * @throws NullPointerException if the specified element is null and this 345 * list does not permit null elements 346 * (<a href="Collection.html#optional-restrictions">optional</a>) 347 */ 348 @Override 349 public int lastIndexOf(Object o) { 350 return 0; 351 } 352 353 private char set(final int index, final char k) { 354 if (index >= size) 355 throw new IndexOutOfBoundsException("Index (" + index + ") is greater than or equal to list size (" + size + ")"); 356 char old = a[index]; 357 a[index] = k; 358 return old; 359 } 360 361 public boolean addAll(int index, final Collection<? extends Character> c) { 362 ensureIndex(index); 363 int n = c.size(); 364 if (n == 0) return false; 365 Iterator<? extends Character> i = c.iterator(); 366 while (n-- != 0) 367 add(index++, i.next()); 368 return true; 369 } 370 371 /** 372 * Removes from this list all of its elements that are contained in the 373 * specified collection (optional operation). 374 * 375 * @param c collection containing elements to be removed from this list 376 * @return <tt>true</tt> if this list changed as a result of the call 377 * @throws UnsupportedOperationException if the <tt>removeAll</tt> operation 378 * is not supported by this list 379 * @throws ClassCastException if the class of an element of this list 380 * is incompatible with the specified collection 381 * (<a href="Collection.html#optional-restrictions">optional</a>) 382 * @throws NullPointerException if this list contains a null element and the 383 * specified collection does not permit null elements 384 * (<a href="Collection.html#optional-restrictions">optional</a>), 385 * or if the specified collection is null 386 * @see #remove(Object) 387 * @see #contains(Object) 388 */ 389 @Override 390 public boolean removeAll(Collection<?> c) { 391 return false; 392 } 393 394 /** 395 * Retains only the elements in this list that are contained in the 396 * specified collection (optional operation). In other words, removes 397 * from this list all of its elements that are not contained in the 398 * specified collection. 399 * 400 * @param c collection containing elements to be retained in this list 401 * @return <tt>true</tt> if this list changed as a result of the call 402 * @throws UnsupportedOperationException if the <tt>retainAll</tt> operation 403 * is not supported by this list 404 * @throws ClassCastException if the class of an element of this list 405 * is incompatible with the specified collection 406 * (<a href="Collection.html#optional-restrictions">optional</a>) 407 * @throws NullPointerException if this list contains a null element and the 408 * specified collection does not permit null elements 409 * (<a href="Collection.html#optional-restrictions">optional</a>), 410 * or if the specified collection is null 411 * @see #remove(Object) 412 * @see #contains(Object) 413 */ 414 @Override 415 public boolean retainAll(Collection<?> c) { 416 return false; 417 } 418 419 public void clear() { 420 size = 0; 421 //if (ASSERTS) assert size <= a.length; 422 } 423 424 public int size() { 425 return size; 426 } 427 428 public void size(final int size) { 429 if (size > a.length) ensureCapacity(size); 430 if (size > this.size) Arrays.fill(a, this.size, size, ((char) 0)); 431 this.size = size; 432 } 433 434 public boolean isEmpty() { 435 return size == 0; 436 } 437 438 /** 439 * Trims this array list so that the capacity is equal to the size. 440 * 441 * @see java.util.ArrayList#trimToSize() 442 */ 443 public void trim() { 444 trim(0); 445 } 446 447 /** 448 * Trims the backing array if it is too large. 449 * <p> 450 * If the current array length is smaller than or equal to <code>n</code>, this method does nothing. Otherwise, it trims the array length to the maximum between <code>n</code> and {@link #size()}. 451 * <p> 452 * <P>This method is useful when reusing lists. {@linkplain #clear() Clearing a list} leaves the array length untouched. If you are reusing a list many times, you can call this method with a 453 * typical size to avoid keeping around a very large array just because of a few large transient lists. 454 * 455 * @param n the threshold for the trimming. 456 */ 457 458 private void trim(final int n) { 459 if (n >= a.length || size == a.length) return; 460 final char t[] = new char[Math.max(n, size)]; 461 System.arraycopy(a, 0, t, 0, size); 462 a = t; 463 //if (ASSERTS) assert size <= a.length; 464 } 465 466 /** 467 * Copies element of this type-specific list into the given array using optimized system calls. 468 * 469 * @param from the start index (inclusive). 470 * @param a the destination array. 471 * @param offset the offset into the destination array where to store the first element copied. 472 * @param length the number of elements to be copied. 473 */ 474 private void getElements(final int from, final char[] a, final int offset, final int length) { 475 CharArrays.ensureOffsetLength(a, offset, length); 476 System.arraycopy(this.a, from, a, offset, length); 477 } 478 479 480 /** 481 * Removes elements of this type-specific list using optimized system calls. 482 * 483 * @param from the start index (inclusive). 484 * @param to the end index (exclusive). 485 */ 486 public void removeElements(final int from, final int to) { 487 CharArrays.ensureFromTo(size, from, to); 488 System.arraycopy(a, to, a, from, size - to); 489 size -= (to - from); 490 } 491 492 /** 493 * Adds elements to this type-specific list using optimized system calls. 494 * 495 * @param index the index at which to add elements. 496 * @param a the array containing the elements. 497 * @param offset the offset of the first element to add. 498 * @param length the number of elements to add. 499 */ 500 public void addElements(final int index, final char a[], final int offset, final int length) { 501 ensureIndex(index); 502 CharArrays.ensureOffsetLength(a, offset, length); 503 grow(size + length); 504 System.arraycopy(this.a, index, this.a, index + length, size - index); 505 System.arraycopy(a, offset, this.a, index, length); 506 size += length; 507 } 508 509 private char[] toCharArray(char a[]) { 510 if (a == null || a.length < size) a = new char[size]; 511 System.arraycopy(this.a, 0, a, 0, size); 512 return a; 513 } 514 515 public boolean addAll(final int index, final CharArrayList l) { 516 ensureIndex(index); 517 final int n = l.size(); 518 if (n == 0) return false; 519 grow(size + n); 520 if (index != size) System.arraycopy(a, index, a, index + n, size - index); 521 l.getElements(0, a, index, n); 522 size += n; 523 //if (ASSERTS) assert size <= a.length; 524 return true; 525 } 526 527 public class CharListIterator implements Iterator<Character>, ListIterator<Character> { 528 529 public CharListIterator(int idx) { 530 index = idx; 531 } 532 533 /** 534 * Delegates to the corresponding type-specific method. 535 */ 536 public Character previous() { 537 return previousChar(); 538 } 539 540 int index, pos = index, last = -1; 541 542 public boolean hasNext() { 543 return pos < size; 544 } 545 546 public boolean hasPrevious() { 547 return pos > 0; 548 } 549 550 public char nextChar() { 551 if (!hasNext()) throw new NoSuchElementException(); 552 return a[last = pos++]; 553 } 554 555 public char previousChar() { 556 if (!hasPrevious()) throw new NoSuchElementException(); 557 return a[last = --pos]; 558 } 559 560 public int nextIndex() { 561 return pos; 562 } 563 564 public int previousIndex() { 565 return pos - 1; 566 } 567 568 /** 569 * Delegates to the corresponding type-specific method. 570 */ 571 public void set(Character ok) { 572 set(ok.charValue()); 573 } 574 575 /** 576 * Delegates to the corresponding type-specific method. 577 */ 578 public void add(Character ok) { 579 add(ok.charValue()); 580 } 581 582 public void add(char k) { 583 if (last == -1) throw new IllegalStateException(); 584 CharArrayList.this.add(pos++, k); 585 last = -1; 586 } 587 588 589 public void set(char k) { 590 if (last == -1) throw new IllegalStateException(); 591 CharArrayList.this.set(last, k); 592 } 593 594 public void remove() { 595 if (last == -1) throw new IllegalStateException(); 596 CharArrayList.this.removeChar(last); 597 /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */ 598 if (last < pos) pos--; 599 last = -1; 600 } 601 602 /** 603 * Delegates to the corresponding type-specific method. 604 * 605 * @deprecated Please use the corresponding type-specific method instead. 606 */ 607 @Deprecated 608 public Character next() { 609 return nextChar(); 610 } 611 612 /** 613 * This method just iterates the type-specific version of {@link #next()} for at most <code>n</code> times, stopping if {@link #hasNext()} becomes false. 614 */ 615 public int skip(final int n) { 616 int i = n; 617 while (i-- != 0 && hasNext()) 618 nextChar(); 619 return n - i - 1; 620 } 621 622 } 623 624 public CharListIterator iterator() { 625 return listIterator(); 626 } 627 628 public CharListIterator listIterator() { 629 return listIterator(0); 630 } 631 632 public CharListIterator listIterator(final int index) { 633 ensureIndex(index); 634 return new CharListIterator(index); 635 } 636 637 /** 638 * Returns a view of the portion of this list between the specified 639 * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive. (If 640 * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is 641 * empty.) The returned list is backed by this list, so non-structural 642 * changes in the returned list are reflected in this list, and vice-versa. 643 * The returned list supports all of the optional list operations supported 644 * by this list.<p> 645 * <p> 646 * This method eliminates the need for explicit range operations (of 647 * the sort that commonly exist for arrays). Any operation that expects 648 * a list can be used as a range operation by passing a subList view 649 * instead of a whole list. For example, the following idiom 650 * removes a range of elements from a list: 651 * <pre>{@code 652 * list.subList(from, to).clear(); 653 * }</pre> 654 * Similar idioms may be constructed for <tt>indexOf</tt> and 655 * <tt>lastIndexOf</tt>, and all of the algorithms in the 656 * <tt>Collections</tt> class can be applied to a subList.<p> 657 * <p> 658 * The semantics of the list returned by this method become undefined if 659 * the backing list (i.e., this list) is <i>structurally modified</i> in 660 * any way other than via the returned list. (Structural modifications are 661 * those that change the size of this list, or otherwise perturb it in such 662 * a fashion that iterations in progress may yield incorrect results.) 663 * 664 * @param fromIndex low endpoint (inclusive) of the subList 665 * @param toIndex high endpoint (exclusive) of the subList 666 * @return a view of the specified range within this list 667 * @throws IndexOutOfBoundsException for an illegal endpoint index value 668 * (<tt>fromIndex < 0 || toIndex > size || 669 * fromIndex > toIndex</tt>) 670 */ 671 @Override 672 public List<Character> subList(int fromIndex, int toIndex) { 673 return new CharArrayList(a, fromIndex, toIndex - fromIndex); 674 } 675 676 public CharArrayList clone() { 677 CharArrayList c = new CharArrayList(size); 678 System.arraycopy(a, 0, c.a, 0, size); 679 c.size = size; 680 return c; 681 } 682 683 /** 684 * Compares this type-specific array list to another one. 685 * <p> 686 * <P>This method exists only for sake of efficiency. The implementation inherited from the abstract implementation would already work. 687 * 688 * @param l a type-specific array list. 689 * @return true if the argument contains the same elements of this type-specific array list. 690 */ 691 public boolean equals(final CharArrayList l) { 692 if (l == this) return true; 693 int s = size(); 694 if (s != l.size()) return false; 695 final char[] a1 = a; 696 final char[] a2 = l.a; 697 while (s-- != 0) 698 if (a1[s] != a2[s]) return false; 699 return true; 700 } 701 702 /** 703 * Compares this array list to another array list. 704 * <p> 705 * <P>This method exists only for sake of efficiency. The implementation inherited from the abstract implementation would already work. 706 * 707 * @param l an array list. 708 * @return a negative integer, zero, or a positive integer as this list is lexicographically less than, equal to, or greater than the argument. 709 */ 710 711 public int compareTo(final CharArrayList l) { 712 final int s1 = size(), s2 = l.size(); 713 final char a1[] = a, a2[] = l.a; 714 char e1, e2; 715 int r, i; 716 for (i = 0; i < s1 && i < s2; i++) { 717 e1 = a1[i]; 718 e2 = a2[i]; 719 if ((r = (e1 - e2)) != 0) return r; 720 } 721 return i < s2 ? -1 : (i < s1 ? 1 : 0); 722 } 723 724 /** 725 * Compares this list to another object. If the argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise, it throws a <code>ClassCastException</code>. 726 * 727 * @param l a list. 728 * @return if the argument is a {@link java.util.List}, a negative integer, zero, or a positive integer as this list is lexicographically less than, equal to, or greater than the argument. 729 * @throws ClassCastException if the argument is not a list. 730 */ 731 732 public int compareTo(final List<? extends Character> l) { 733 if (l == this) return 0; 734 if (l instanceof CharArrayList) { 735 final CharListIterator i1 = listIterator(), i2 = ((CharArrayList) l).listIterator(); 736 int r; 737 char e1, e2; 738 while (i1.hasNext() && i2.hasNext()) { 739 e1 = i1.nextChar(); 740 e2 = i2.nextChar(); 741 if ((r = (e1 - e2)) != 0) return r; 742 } 743 return i2.hasNext() ? -1 : (i1.hasNext() ? 1 : 0); 744 } 745 ListIterator<? extends Character> i1 = listIterator(), i2 = l.listIterator(); 746 int r; 747 while (i1.hasNext() && i2.hasNext()) { 748 if ((r = ((Comparable<? super Character>) i1.next()).compareTo(i2.next())) != 0) return r; 749 } 750 return i2.hasNext() ? -1 : (i1.hasNext() ? 1 : 0); 751 } 752 753 /** 754 * Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}. 755 * 756 * @return the hash code for this list. 757 */ 758 public int hashCode() { 759 CharListIterator i = iterator(); 760 int h = 1, s = size(); 761 while (s-- != 0) { 762 char k = i.nextChar(); 763 h = 31 * h + (k); 764 } 765 return h; 766 } 767 768 769 /** 770 * Delegates to the corresponding type-specific method. 771 * 772 * @deprecated Please use the corresponding type-specific method instead. 773 */ 774 @Deprecated 775 public Character get(final int index) { 776 return getChar(index); 777 } 778 779 780 /** 781 * Ensures that the given index is non-negative and not greater than the list size. 782 * 783 * @param index an index. 784 * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size. 785 */ 786 private void ensureIndex(final int index) { 787 if (index < 0) throw new IndexOutOfBoundsException("Index (" + index + ") is negative"); 788 if (index > size()) 789 throw new IndexOutOfBoundsException("Index (" + index + ") is greater than list size (" + (size()) + ")"); 790 } 791 792 /** 793 * Ensures that the given index is non-negative and smaller than the list size. 794 * 795 * @param index an index. 796 * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size. 797 */ 798 protected void ensureRestrictedIndex(final int index) { 799 if (index < 0) throw new IndexOutOfBoundsException("Index (" + index + ") is negative"); 800 if (index >= size()) 801 throw new IndexOutOfBoundsException("Index (" + index + ") is greater than or equal to list size (" + (size()) + ")"); 802 } 803 804 805 private boolean contains(final char k) { 806 return indexOf(k) >= 0; 807 } 808 809 /** 810 * Delegates to the corresponding type-specific method. 811 */ 812 public boolean contains(final Object o) { 813 return contains(((((Character) (o)).charValue()))); 814 } 815 816 817 public Object[] toArray() { 818 final Object[] a = new Object[size()]; 819 objectUnwrap(iterator(), a); 820 return a; 821 } 822 823 /** 824 * Returns an array containing all of the elements in this list in 825 * proper sequence (from first to last element); the runtime type of 826 * the returned array is that of the specified array. If the list fits 827 * in the specified array, it is returned therein. Otherwise, a new 828 * array is allocated with the runtime type of the specified array and 829 * the size of this list. 830 * <p> 831 * <p>If the list fits in the specified array with room to spare (i.e., 832 * the array has more elements than the list), the element in the array 833 * immediately following the end of the list is set to <tt>null</tt>. 834 * (This is useful in determining the length of the list <i>only</i> if 835 * the caller knows that the list does not contain any null elements.) 836 * <p> 837 * <p>Like the {@link #toArray()} method, this method acts as bridge between 838 * array-based and collection-based APIs. Further, this method allows 839 * precise control over the runtime type of the output array, and may, 840 * under certain circumstances, be used to save allocation costs. 841 * <p> 842 * <p>Suppose <tt>x</tt> is a list known to contain only strings. 843 * The following code can be used to dump the list into a newly 844 * allocated array of <tt>String</tt>: 845 * <p> 846 * <pre>{@code 847 * String[] y = x.toArray(new String[0]); 848 * }</pre> 849 * <p> 850 * Note that <tt>toArray(new Object[0])</tt> is identical in function to 851 * <tt>toArray()</tt>. 852 * 853 * @param a the array into which the elements of this list are to 854 * be stored, if it is big enough; otherwise, a new array of the 855 * same runtime type is allocated for this purpose. 856 * @return an array containing the elements of this list 857 * @throws ArrayStoreException if the runtime type of the specified array 858 * is not a supertype of the runtime type of every element in 859 * this list 860 * @throws NullPointerException if the specified array is null 861 */ 862 @Override 863 @SuppressWarnings("unchecked") 864 public <T> T[] toArray(T[] a) { 865 Character[] b; 866 if (a.length < size()) b = new Character[size()]; 867 else b = (Character[]) a; 868 objectUnwrap(iterator(), b); 869 return (T[]) b; 870 871 } 872 873 public Character[] toArray(Character[] a) { 874 if (a.length < size()) a = new Character[size()]; 875 objectUnwrap(iterator(), a); 876 return a; 877 } 878 879 880 /** 881 * Delegates to the corresponding type-specific method. 882 */ 883 public boolean add(final Character o) { 884 return add(o.charValue()); 885 } 886 887 888 /** 889 * Delegates to the type-specific <code>rem()</code> method. 890 */ 891 public boolean remove(Object ok) { 892 return rem((((Character) (ok)))); 893 } 894 895 896 /** 897 * Checks whether this collection contains all elements from the given collection. 898 * 899 * @param c a collection. 900 * @return <code>true</code> if this collection contains all elements of the argument. 901 */ 902 public boolean containsAll(Collection<?> c) { 903 int n = c.size(); 904 final Iterator<?> i = c.iterator(); 905 while (n-- != 0) 906 if (!contains(i.next())) return false; 907 return true; 908 } 909 910 /** 911 * Adds all elements of the given collection to this collection. 912 * 913 * @param c a collection. 914 * @return <code>true</code> if this collection changed as a result of the call. 915 */ 916 public boolean addAll(Collection<? extends Character> c) { 917 boolean retVal = false; 918 final Iterator<? extends Character> i = c.iterator(); 919 int n = c.size(); 920 while (n-- != 0) 921 if (add(i.next())) retVal = true; 922 return retVal; 923 } 924 925 926 /** 927 * Unwraps an iterator into an array starting at a given offset for a given number of elements. 928 * <p> 929 * <P>This method iterates over the given type-specific iterator and stores the elements returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>. The 930 * number of actually unwrapped elements is returned (it may be less than <code>max</code> if the iterator emits less than <code>max</code> elements). 931 * 932 * @param i a type-specific iterator. 933 * @param array an array to contain the output of the iterator. 934 * @return the number of elements unwrapped. 935 */ 936 private static <K> int objectUnwrap(final Iterator<? extends K> i, final K array[]) { 937 int j = array.length, offset = 0; 938 while (j-- != 0 && i.hasNext()) 939 array[offset++] = i.next(); 940 return array.length - j - 1; 941 } 942 943 944 public char[] toArray(char a[]) { 945 return toCharArray(a); 946 } 947 948 public char[] toCharArray() { 949 return toCharArray(null); 950 } 951 952 @Override 953 public String toString() { 954 return new String(a, 0, size); 955 } 956 957 /** 958 * Unwraps an iterator into an array starting at a given offset for a given number of elements. 959 * <p> 960 * <P>This method iterates over the given type-specific iterator and stores the elements returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>. The 961 * number of actually unwrapped elements is returned (it may be less than <code>max</code> if the iterator emits less than <code>max</code> elements). 962 * 963 * @param i a type-specific iterator. 964 * @param array an array to contain the output of the iterator. 965 * @return the number of elements unwrapped. 966 */ 967 public static int unwrap(final CharListIterator i, final char array[]) { 968 int j = array.length, offset = 0; 969 while (j-- != 0 && i.hasNext()) 970 array[offset++] = i.nextChar(); 971 return array.length - j - 1; 972 } 973 974 975 private static class CharArrays /** A static, final, empty array. */ 976 { 977 public static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 978 public final static char[] EMPTY_ARRAY = {}; 979 980 981 /** 982 * Ensures that an array can contain the given number of entries. 983 * <p> 984 * <P>If you cannot foresee whether this array will need again to be enlarged, you should probably use <code>grow()</code> instead. 985 * 986 * @param array an array. 987 * @param length the new minimum length for this array. 988 * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise, an array with <code>length</code> entries whose first <code>array.length</code> entries are the same 989 * as those of <code>array</code>. 990 */ 991 public static char[] ensureCapacity(final char[] array, final int length) { 992 if (length > array.length) { 993 final char t[] = 994 new char[length]; 995 System.arraycopy(array, 0, t, 0, array.length); 996 return t; 997 } 998 return array; 999 } 1000 1001 /** 1002 * Ensures that an array can contain the given number of entries, preserving just a part of the array. 1003 * 1004 * @param array an array. 1005 * @param length the new minimum length for this array. 1006 * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary. 1007 * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise, an array with <code>length</code> entries whose first <code>preserve</code> entries are the same as 1008 * those of <code>array</code>. 1009 */ 1010 public static char[] ensureCapacity(final char[] array, final int length, final int preserve) { 1011 if (length > array.length) { 1012 final char t[] = 1013 new char[length]; 1014 System.arraycopy(array, 0, t, 0, preserve); 1015 return t; 1016 } 1017 return array; 1018 } 1019 1020 /** 1021 * Grows the given array to the maximum between the given length and the current length multiplied by two, provided that the given length is larger than the current length. 1022 * <p> 1023 * <P>If you want complete control on the array growth, you should probably use <code>ensureCapacity()</code> instead. 1024 * 1025 * @param array an array. 1026 * @param length the new minimum length for this array. 1027 * @return <code>array</code>, if it can contain <code>length</code> entries; otherwise, an array with max(<code>length</code>,<code>array.length</code>/φ) entries whose first 1028 * <code>array.length</code> entries are the same as those of <code>array</code>. 1029 */ 1030 public static char[] grow(final char[] array, final int length) { 1031 if (length > array.length) { 1032 final int newLength = (int) Math.max(Math.min(2L * array.length, MAX_ARRAY_SIZE), length); 1033 final char t[] = 1034 new char[newLength]; 1035 System.arraycopy(array, 0, t, 0, array.length); 1036 return t; 1037 } 1038 return array; 1039 } 1040 1041 /** 1042 * Grows the given array to the maximum between the given length and the current length multiplied by two, provided that the given length is larger than the current length, preserving just a part 1043 * of the array. 1044 * <p> 1045 * <P>If you want complete control on the array growth, you should probably use <code>ensureCapacity()</code> instead. 1046 * 1047 * @param array an array. 1048 * @param length the new minimum length for this array. 1049 * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary. 1050 * @return <code>array</code>, if it can contain <code>length</code> entries; otherwise, an array with max(<code>length</code>,<code>array.length</code>/φ) entries whose first 1051 * <code>preserve</code> entries are the same as those of <code>array</code>. 1052 */ 1053 public static char[] grow(final char[] array, final int length, final int preserve) { 1054 if (length > array.length) { 1055 final int newLength = (int) Math.max(Math.min(2L * array.length, MAX_ARRAY_SIZE), length); 1056 final char t[] = 1057 new char[newLength]; 1058 System.arraycopy(array, 0, t, 0, preserve); 1059 return t; 1060 } 1061 return array; 1062 } 1063 1064 /** 1065 * Trims the given array to the given length. 1066 * 1067 * @param array an array. 1068 * @param length the new maximum length for the array. 1069 * @return <code>array</code>, if it contains <code>length</code> entries or less; otherwise, an array with <code>length</code> entries whose entries are the same as the first <code>length</code> 1070 * entries of <code>array</code>. 1071 */ 1072 public static char[] trim(final char[] array, final int length) { 1073 if (length >= array.length) return array; 1074 final char t[] = 1075 length == 0 ? EMPTY_ARRAY : new char[length]; 1076 System.arraycopy(array, 0, t, 0, length); 1077 return t; 1078 } 1079 1080 /** 1081 * Sets the length of the given array. 1082 * 1083 * @param array an array. 1084 * @param length the new length for the array. 1085 * @return <code>array</code>, if it contains exactly <code>length</code> entries; otherwise, if it contains <em>more</em> than <code>length</code> entries, an array with <code>length</code> 1086 * entries whose entries are the same as the first <code>length</code> entries of <code>array</code>; otherwise, an array with <code>length</code> entries whose first <code>array.length</code> 1087 * entries are the same as those of <code>array</code>. 1088 */ 1089 public static char[] setLength(final char[] array, final int length) { 1090 if (length == array.length) return array; 1091 if (length < array.length) return trim(array, length); 1092 return ensureCapacity(array, length); 1093 } 1094 1095 /** 1096 * Returns a copy of a portion of an array. 1097 * 1098 * @param array an array. 1099 * @param offset the first element to copy. 1100 * @param length the number of elements to copy. 1101 * @return a new array containing <code>length</code> elements of <code>array</code> starting at <code>offset</code>. 1102 */ 1103 public static char[] copy(final char[] array, final int offset, final int length) { 1104 ensureOffsetLength(array, offset, length); 1105 final char[] a = 1106 length == 0 ? EMPTY_ARRAY : new char[length]; 1107 System.arraycopy(array, offset, a, 0, length); 1108 return a; 1109 } 1110 1111 /** 1112 * Returns a copy of an array. 1113 * 1114 * @param array an array. 1115 * @return a copy of <code>array</code>. 1116 */ 1117 public static char[] copy(final char[] array) { 1118 char[] next = new char[array.length]; 1119 System.arraycopy(array, 0, next, 0, array.length); 1120 return next; 1121 } 1122 1123 /** 1124 * Fills the given array with the given value. 1125 * 1126 * @param array an array. 1127 * @param value the new value for all elements of the array. 1128 * @deprecated Please use the corresponding {@link java.util.Arrays} method. 1129 */ 1130 @Deprecated 1131 public static void fill(final char[] array, final char value) { 1132 int i = array.length; 1133 while (i-- != 0) 1134 array[i] = value; 1135 } 1136 1137 /** 1138 * Fills a portion of the given array with the given value. 1139 * 1140 * @param array an array. 1141 * @param from the starting index of the portion to fill (inclusive). 1142 * @param to the end index of the portion to fill (exclusive). 1143 * @param value the new value for all elements of the specified portion of the array. 1144 * @deprecated Please use the corresponding {@link java.util.Arrays} method. 1145 */ 1146 @Deprecated 1147 public static void fill(final char[] array, final int from, int to, final char value) { 1148 ensureFromTo(array, from, to); 1149 if (from == 0) while (to-- != 0) 1150 array[to] = value; 1151 else for (int i = from; i < to; i++) 1152 array[i] = value; 1153 } 1154 1155 /** 1156 * Returns true if the two arrays are element-wise equal. 1157 * 1158 * @param a1 an array. 1159 * @param a2 another array. 1160 * @return true if the two arrays are of the same length, and their elements are equal. 1161 * @deprecated Please use the corresponding {@link java.util.Arrays} method, which is intrinsic in recent JVMs. 1162 */ 1163 @Deprecated 1164 public static boolean equals(final char[] a1, final char a2[]) { 1165 int i = a1.length; 1166 if (i != a2.length) return false; 1167 while (i-- != 0) 1168 if (!((a1[i]) == (a2[i]))) return false; 1169 return true; 1170 } 1171 1172 /** 1173 * Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array. 1174 * <p> 1175 * <P>This method may be used whenever an array range check is needed. 1176 * 1177 * @param a an array. 1178 * @param from a start index (inclusive). 1179 * @param to an end index (exclusive). 1180 * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>. 1181 * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than the array length or negative. 1182 */ 1183 public static void ensureFromTo(final char[] a, final int from, final int to) { 1184 ensureFromTo(a.length, from, to); 1185 } 1186 1187 /** 1188 * Ensures that a range given by an offset and a length fits an array. 1189 * <p> 1190 * <P>This method may be used whenever an array range check is needed. 1191 * 1192 * @param a an array. 1193 * @param offset a start index. 1194 * @param length a length (the number of elements in the range). 1195 * @throws IllegalArgumentException if <code>length</code> is negative. 1196 * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than the array length. 1197 */ 1198 public static void ensureOffsetLength(final char[] a, final int offset, final int length) { 1199 ensureOffsetLength(a.length, offset, length); 1200 } 1201 1202 /** 1203 * Ensures that two arrays are of the same length. 1204 * 1205 * @param a an array. 1206 * @param b another array. 1207 * @throws IllegalArgumentException if the two argument arrays are not of the same length. 1208 */ 1209 public static void ensureSameLength(final char[] a, final char[] b) { 1210 if (a.length != b.length) 1211 throw new IllegalArgumentException("Array size mismatch: " + a.length + " != " + b.length); 1212 } 1213 1214 /** 1215 * Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array of given length. 1216 * <p> 1217 * <P>This method may be used whenever an array range check is needed. 1218 * 1219 * @param arrayLength an array length. 1220 * @param from a start index (inclusive). 1221 * @param to an end index (inclusive). 1222 * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>. 1223 * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than <code>arrayLength</code> or negative. 1224 */ 1225 public static void ensureFromTo(final int arrayLength, final int from, final int to) { 1226 if (from < 0) throw new ArrayIndexOutOfBoundsException("Start index (" + from + ") is negative"); 1227 if (from > to) 1228 throw new IllegalArgumentException("Start index (" + from + ") is greater than end index (" + to + ")"); 1229 if (to > arrayLength) 1230 throw new ArrayIndexOutOfBoundsException("End index (" + to + ") is greater than array length (" + arrayLength + ")"); 1231 } 1232 1233 1234 /** 1235 * Ensures that a range given by an offset and a length fits an array of given length. 1236 * <p> 1237 * <P>This method may be used whenever an array range check is needed. 1238 * 1239 * @param arrayLength an array length. 1240 * @param offset a start index for the fragment 1241 * @param length a length (the number of elements in the fragment). 1242 * @throws IllegalArgumentException if <code>length</code> is negative. 1243 * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than <code>arrayLength</code>. 1244 */ 1245 public static void ensureOffsetLength(final int arrayLength, final int offset, final int length) { 1246 if (offset < 0) throw new ArrayIndexOutOfBoundsException("Offset (" + offset + ") is negative"); 1247 if (length < 0) throw new IllegalArgumentException("Length (" + length + ") is negative"); 1248 if (offset + length > arrayLength) 1249 throw new ArrayIndexOutOfBoundsException("Last index (" + (offset + length) + ") is greater than array length (" + arrayLength + ")"); 1250 } 1251 } 1252}