1 7 8 package java.util.concurrent; 9 import java.util.*; 10 11 39 public class CopyOnWriteArrayList<E> 40 implements List<E>, RandomAccess, Cloneable , java.io.Serializable { 41 private static final long serialVersionUID = 8673264195747942595L; 42 43 47 private volatile transient E[] array; 48 49 53 private E[] array() { return array; } 54 55 58 public CopyOnWriteArrayList() { 59 array = (E[]) new Object [0]; 60 } 61 62 68 public CopyOnWriteArrayList(Collection<? extends E> c) { 69 array = (E[]) new Object [c.size()]; 70 Iterator<? extends E> i = c.iterator(); 71 int size = 0; 72 while (i.hasNext()) 73 array[size++] = i.next(); 74 } 75 76 82 public CopyOnWriteArrayList(E[] toCopyIn) { 83 copyIn(toCopyIn, 0, toCopyIn.length); 84 } 85 86 98 private synchronized void copyIn(E[] toCopyIn, int first, int n) { 99 array = (E[]) new Object [n]; 100 System.arraycopy(toCopyIn, first, array, 0, n); 101 } 102 103 108 public int size() { 109 return array().length; 110 } 111 112 118 public boolean isEmpty() { 119 return size() == 0; 120 } 121 122 129 public boolean contains(Object elem) { 130 E[] elementData = array(); 131 int len = elementData.length; 132 return indexOf(elem, elementData, len) >= 0; 133 } 134 135 144 public int indexOf(Object elem) { 145 E[] elementData = array(); 146 int len = elementData.length; 147 return indexOf(elem, elementData, len); 148 } 149 150 154 private static int indexOf(Object elem, Object [] elementData, int len) { 155 if (elem == null) { 156 for (int i = 0; i < len; i++) 157 if (elementData[i]==null) 158 return i; 159 } else { 160 for (int i = 0; i < len; i++) 161 if (elem.equals(elementData[i])) 162 return i; 163 } 164 return -1; 165 } 166 167 179 public int indexOf(E elem, int index) { 180 E[] elementData = array(); 181 int elementCount = elementData.length; 182 183 if (elem == null) { 184 for (int i = index ; i < elementCount ; i++) 185 if (elementData[i]==null) 186 return i; 187 } else { 188 for (int i = index ; i < elementCount ; i++) 189 if (elem.equals(elementData[i])) 190 return i; 191 } 192 return -1; 193 } 194 195 203 public int lastIndexOf(Object elem) { 204 E[] elementData = array(); 205 int len = elementData.length; 206 return lastIndexOf(elem, elementData, len); 207 } 208 209 private static int lastIndexOf(Object elem, Object [] elementData, int len) { 210 if (elem == null) { 211 for (int i = len-1; i >= 0; i--) 212 if (elementData[i]==null) 213 return i; 214 } else { 215 for (int i = len-1; i >= 0; i--) 216 if (elem.equals(elementData[i])) 217 return i; 218 } 219 return -1; 220 } 221 222 232 public int lastIndexOf(E elem, int index) { 233 E[] elementData = array(); 235 if (elem == null) { 236 for (int i = index; i >= 0; i--) 237 if (elementData[i]==null) 238 return i; 239 } else { 240 for (int i = index; i >= 0; i--) 241 if (elem.equals(elementData[i])) 242 return i; 243 } 244 return -1; 245 } 246 247 253 public Object clone() { 254 try { 255 E[] elementData = array(); 256 CopyOnWriteArrayList <E> v = (CopyOnWriteArrayList <E>)super.clone(); 257 v.array = (E[]) new Object [elementData.length]; 258 System.arraycopy(elementData, 0, v.array, 0, elementData.length); 259 return v; 260 } catch (CloneNotSupportedException e) { 261 throw new InternalError (); 263 } 264 } 265 266 272 public Object [] toArray() { 273 Object [] elementData = array(); 274 Object [] result = new Object [elementData.length]; 275 System.arraycopy(elementData, 0, result, 0, elementData.length); 276 return result; 277 } 278 279 300 public <T> T[] toArray(T a[]) { 301 E[] elementData = array(); 302 303 if (a.length < elementData.length) 304 a = (T[]) 305 java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), 306 elementData.length); 307 308 System.arraycopy(elementData, 0, a, 0, elementData.length); 309 310 if (a.length > elementData.length) 311 a[elementData.length] = null; 312 313 return a; 314 } 315 316 318 326 public E get(int index) { 327 E[] elementData = array(); 328 rangeCheck(index, elementData.length); 329 return elementData[index]; 330 } 331 332 342 public synchronized E set(int index, E element) { 343 int len = array.length; 344 rangeCheck(index, len); 345 E oldValue = array[index]; 346 347 boolean same = (oldValue == element || 348 (element != null && element.equals(oldValue))); 349 if (!same) { 350 E[] newArray = (E[]) new Object [len]; 351 System.arraycopy(array, 0, newArray, 0, len); 352 newArray[index] = element; 353 array = newArray; 354 } 355 return oldValue; 356 } 357 358 364 public synchronized boolean add(E element) { 365 int len = array.length; 366 E[] newArray = (E[]) new Object [len+1]; 367 System.arraycopy(array, 0, newArray, 0, len); 368 newArray[len] = element; 369 array = newArray; 370 return true; 371 } 372 373 383 public synchronized void add(int index, E element) { 384 int len = array.length; 385 if (index > len || index < 0) 386 throw new IndexOutOfBoundsException ("Index: "+index+", Size: "+len); 387 388 E[] newArray = (E[]) new Object [len+1]; 389 System.arraycopy(array, 0, newArray, 0, index); 390 newArray[index] = element; 391 System.arraycopy(array, index, newArray, index+1, len - index); 392 array = newArray; 393 } 394 395 405 public synchronized E remove(int index) { 406 int len = array.length; 407 rangeCheck(index, len); 408 E oldValue = array[index]; 409 E[] newArray = (E[]) new Object [len-1]; 410 System.arraycopy(array, 0, newArray, 0, index); 411 int numMoved = len - index - 1; 412 if (numMoved > 0) 413 System.arraycopy(array, index+1, newArray, index, numMoved); 414 array = newArray; 415 return oldValue; 416 } 417 418 430 public synchronized boolean remove(Object o) { 431 int len = array.length; 432 if (len == 0) return false; 433 434 437 int newlen = len-1; 438 E[] newArray = (E[]) new Object [newlen]; 439 440 for (int i = 0; i < newlen; ++i) { 441 if (o == array[i] || 442 (o != null && o.equals(array[i]))) { 443 for (int k = i + 1; k < len; ++k) newArray[k-1] = array[k]; 445 array = newArray; 446 return true; 447 } else 448 newArray[i] = array[i]; 449 } 450 452 if (o == array[newlen] || 453 (o != null && o.equals(array[newlen]))) { 454 array = newArray; 455 return true; 456 } else 457 return false; } 459 460 461 474 private synchronized void removeRange(int fromIndex, int toIndex) { 475 int len = array.length; 476 477 if (fromIndex < 0 || fromIndex >= len || 478 toIndex > len || toIndex < fromIndex) 479 throw new IndexOutOfBoundsException (); 480 481 int numMoved = len - toIndex; 482 int newlen = len - (toIndex-fromIndex); 483 E[] newArray = (E[]) new Object [newlen]; 484 System.arraycopy(array, 0, newArray, 0, fromIndex); 485 System.arraycopy(array, toIndex, newArray, fromIndex, numMoved); 486 array = newArray; 487 } 488 489 490 495 public synchronized boolean addIfAbsent(E element) { 496 int len = array.length; 499 E[] newArray = (E[]) new Object [len + 1]; 500 for (int i = 0; i < len; ++i) { 501 if (element == array[i] || 502 (element != null && element.equals(array[i]))) 503 return false; else 505 newArray[i] = array[i]; 506 } 507 newArray[len] = element; 508 array = newArray; 509 return true; 510 } 511 512 523 public boolean containsAll(Collection<?> c) { 524 E[] elementData = array(); 525 int len = elementData.length; 526 Iterator e = c.iterator(); 527 while (e.hasNext()) 528 if (indexOf(e.next(), elementData, len) < 0) 529 return false; 530 531 return true; 532 } 533 534 535 544 public synchronized boolean removeAll(Collection<?> c) { 545 E[] elementData = array; 546 int len = elementData.length; 547 if (len == 0) return false; 548 549 E[] temp = (E[]) new Object [len]; 551 int newlen = 0; 552 for (int i = 0; i < len; ++i) { 553 E element = elementData[i]; 554 if (!c.contains(element)) { 555 temp[newlen++] = element; 556 } 557 } 558 559 if (newlen == len) return false; 560 561 E[] newArray = (E[]) new Object [newlen]; 563 System.arraycopy(temp, 0, newArray, 0, newlen); 564 array = newArray; 565 return true; 566 } 567 568 576 public synchronized boolean retainAll(Collection<?> c) { 577 E[] elementData = array; 578 int len = elementData.length; 579 if (len == 0) return false; 580 581 E[] temp = (E[]) new Object [len]; 582 int newlen = 0; 583 for (int i = 0; i < len; ++i) { 584 E element = elementData[i]; 585 if (c.contains(element)) { 586 temp[newlen++] = element; 587 } 588 } 589 590 if (newlen == len) return false; 591 592 E[] newArray = (E[]) new Object [newlen]; 593 System.arraycopy(temp, 0, newArray, 0, newlen); 594 array = newArray; 595 return true; 596 } 597 598 607 public synchronized int addAllAbsent(Collection<? extends E> c) { 608 int numNew = c.size(); 609 if (numNew == 0) return 0; 610 611 E[] elementData = array; 612 int len = elementData.length; 613 614 E[] temp = (E[]) new Object [numNew]; 615 int added = 0; 616 Iterator<? extends E> e = c.iterator(); 617 while (e.hasNext()) { 618 E element = e.next(); 619 if (indexOf(element, elementData, len) < 0) { 620 if (indexOf(element, temp, added) < 0) { 621 temp[added++] = element; 622 } 623 } 624 } 625 626 if (added == 0) return 0; 627 628 E[] newArray = (E[]) new Object [len+added]; 629 System.arraycopy(elementData, 0, newArray, 0, len); 630 System.arraycopy(temp, 0, newArray, len, added); 631 array = newArray; 632 return added; 633 } 634 635 639 public synchronized void clear() { 640 array = (E[]) new Object [0]; 641 } 642 643 651 public synchronized boolean addAll(Collection<? extends E> c) { 652 int numNew = c.size(); 653 if (numNew == 0) return false; 654 655 int len = array.length; 656 E[] newArray = (E[]) new Object [len+numNew]; 657 System.arraycopy(array, 0, newArray, 0, len); 658 Iterator<? extends E> e = c.iterator(); 659 for (int i=0; i<numNew; i++) 660 newArray[len++] = e.next(); 661 array = newArray; 662 663 return true; 664 } 665 666 681 public synchronized boolean addAll(int index, Collection<? extends E> c) { 682 int len = array.length; 683 if (index > len || index < 0) 684 throw new IndexOutOfBoundsException ("Index: "+index+", Size: "+len); 685 686 int numNew = c.size(); 687 if (numNew == 0) return false; 688 689 E[] newArray = (E[]) new Object [len+numNew]; 690 System.arraycopy(array, 0, newArray, 0, len); 691 int numMoved = len - index; 692 if (numMoved > 0) 693 System.arraycopy(array, index, newArray, index + numNew, numMoved); 694 Iterator<? extends E> e = c.iterator(); 695 for (int i=0; i<numNew; i++) 696 newArray[index++] = e.next(); 697 array = newArray; 698 699 return true; 700 } 701 702 706 private void rangeCheck(int index, int length) { 707 if (index >= length || index < 0) 708 throw new IndexOutOfBoundsException ("Index: "+index+", Size: "+ length); 709 } 710 711 719 private void writeObject(java.io.ObjectOutputStream s) 720 throws java.io.IOException { 721 722 s.defaultWriteObject(); 724 725 E[] elementData = array(); 726 s.writeInt(elementData.length); 728 729 for (int i=0; i<elementData.length; i++) 731 s.writeObject(elementData[i]); 732 } 733 734 738 private void readObject(java.io.ObjectInputStream s) 739 throws java.io.IOException , ClassNotFoundException { 740 741 s.defaultReadObject(); 743 744 int arrayLength = s.readInt(); 746 E[] elementData = (E[]) new Object [arrayLength]; 747 748 for (int i=0; i<elementData.length; i++) 750 elementData[i] = (E) s.readObject(); 751 array = elementData; 752 } 753 754 758 public String toString() { 759 StringBuffer buf = new StringBuffer (); 760 Iterator e = iterator(); 761 buf.append("["); 762 int maxIndex = size() - 1; 763 for (int i = 0; i <= maxIndex; i++) { 764 buf.append(String.valueOf(e.next())); 765 if (i < maxIndex) 766 buf.append(", "); 767 } 768 buf.append("]"); 769 return buf.toString(); 770 } 771 772 773 794 public boolean equals(Object o) { 795 if (o == this) 796 return true; 797 if (!(o instanceof List)) 798 return false; 799 800 List<E> l2 = (List<E>)(o); 801 if (size() != l2.size()) 802 return false; 803 804 ListIterator<E> e1 = listIterator(); 805 ListIterator<E> e2 = l2.listIterator(); 806 while(e1.hasNext()) { 807 E o1 = e1.next(); 808 E o2 = e2.next(); 809 if (!(o1==null ? o2==null : o1.equals(o2))) 810 return false; 811 } 812 return true; 813 } 814 815 822 public int hashCode() { 823 int hashCode = 1; 824 Iterator<E> i = iterator(); 825 while (i.hasNext()) { 826 E obj = i.next(); 827 hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode()); 828 } 829 return hashCode; 830 } 831 832 840 public Iterator<E> iterator() { 841 return new COWIterator<E>(array(), 0); 842 } 843 844 854 public ListIterator<E> listIterator() { 855 return new COWIterator<E>(array(), 0); 856 } 857 858 874 public ListIterator<E> listIterator(final int index) { 875 E[] elementData = array(); 876 int len = elementData.length; 877 if (index<0 || index>len) 878 throw new IndexOutOfBoundsException ("Index: "+index); 879 880 return new COWIterator<E>(array(), index); 881 } 882 883 private static class COWIterator<E> implements ListIterator<E> { 884 885 886 private final E[] array; 887 888 891 private int cursor; 892 893 private COWIterator(E[] elementArray, int initialCursor) { 894 array = elementArray; 895 cursor = initialCursor; 896 } 897 898 public boolean hasNext() { 899 return cursor < array.length; 900 } 901 902 public boolean hasPrevious() { 903 return cursor > 0; 904 } 905 906 public E next() { 907 try { 908 return array[cursor++]; 909 } catch (IndexOutOfBoundsException ex) { 910 throw new NoSuchElementException(); 911 } 912 } 913 914 public E previous() { 915 try { 916 return array[--cursor]; 917 } catch(IndexOutOfBoundsException e) { 918 throw new NoSuchElementException(); 919 } 920 } 921 922 public int nextIndex() { 923 return cursor; 924 } 925 926 public int previousIndex() { 927 return cursor-1; 928 } 929 930 935 936 public void remove() { 937 throw new UnsupportedOperationException (); 938 } 939 940 945 public void set(E o) { 946 throw new UnsupportedOperationException (); 947 } 948 949 954 public void add(E o) { 955 throw new UnsupportedOperationException (); 956 } 957 } 958 959 960 979 public synchronized List<E> subList(int fromIndex, int toIndex) { 980 int len = array.length; 982 if (fromIndex<0 || toIndex>len || fromIndex>toIndex) 983 throw new IndexOutOfBoundsException (); 984 return new COWSubList<E>(this, fromIndex, toIndex); 985 } 986 987 private static class COWSubList<E> extends AbstractList<E> { 988 989 1003 1004 private final CopyOnWriteArrayList <E> l; 1005 private final int offset; 1006 private int size; 1007 private E[] expectedArray; 1008 1009 private COWSubList(CopyOnWriteArrayList <E> list, 1010 int fromIndex, int toIndex) { 1011 l = list; 1012 expectedArray = l.array(); 1013 offset = fromIndex; 1014 size = toIndex - fromIndex; 1015 } 1016 1017 private void checkForComodification() { 1019 if (l.array != expectedArray) 1020 throw new ConcurrentModificationException(); 1021 } 1022 1023 private void rangeCheck(int index) { 1025 if (index<0 || index>=size) 1026 throw new IndexOutOfBoundsException ("Index: "+index+ ",Size: "+size); 1027 } 1028 1029 1030 public E set(int index, E element) { 1031 synchronized(l) { 1032 rangeCheck(index); 1033 checkForComodification(); 1034 E x = l.set(index+offset, element); 1035 expectedArray = l.array; 1036 return x; 1037 } 1038 } 1039 1040 public E get(int index) { 1041 synchronized(l) { 1042 rangeCheck(index); 1043 checkForComodification(); 1044 return l.get(index+offset); 1045 } 1046 } 1047 1048 public int size() { 1049 synchronized(l) { 1050 checkForComodification(); 1051 return size; 1052 } 1053 } 1054 1055 public void add(int index, E element) { 1056 synchronized(l) { 1057 checkForComodification(); 1058 if (index<0 || index>size) 1059 throw new IndexOutOfBoundsException (); 1060 l.add(index+offset, element); 1061 expectedArray = l.array; 1062 size++; 1063 } 1064 } 1065 1066 public void clear() { 1067 synchronized(l) { 1068 checkForComodification(); 1069 l.removeRange(offset, offset+size); 1070 expectedArray = l.array; 1071 size = 0; 1072 } 1073 } 1074 1075 public E remove(int index) { 1076 synchronized(l) { 1077 rangeCheck(index); 1078 checkForComodification(); 1079 E result = l.remove(index+offset); 1080 expectedArray = l.array; 1081 size--; 1082 return result; 1083 } 1084 } 1085 1086 public Iterator<E> iterator() { 1087 synchronized(l) { 1088 checkForComodification(); 1089 return new COWSubListIterator<E>(l, 0, offset, size); 1090 } 1091 } 1092 1093 public ListIterator<E> listIterator(final int index) { 1094 synchronized(l) { 1095 checkForComodification(); 1096 if (index<0 || index>size) 1097 throw new IndexOutOfBoundsException ("Index: "+index+", Size: "+size); 1098 return new COWSubListIterator<E>(l, index, offset, size); 1099 } 1100 } 1101 1102 public List<E> subList(int fromIndex, int toIndex) { 1103 synchronized(l) { 1104 checkForComodification(); 1105 if (fromIndex<0 || toIndex>size) 1106 throw new IndexOutOfBoundsException (); 1107 return new COWSubList<E>(l, fromIndex+offset, toIndex+offset); 1108 } 1109 } 1110 1111 } 1112 1113 1114 private static class COWSubListIterator<E> implements ListIterator<E> { 1115 private final ListIterator<E> i; 1116 private final int index; 1117 private final int offset; 1118 private final int size; 1119 private COWSubListIterator(List<E> l, int index, int offset, int size) { 1120 this.index = index; 1121 this.offset = offset; 1122 this.size = size; 1123 i = l.listIterator(index+offset); 1124 } 1125 1126 public boolean hasNext() { 1127 return nextIndex() < size; 1128 } 1129 1130 public E next() { 1131 if (hasNext()) 1132 return i.next(); 1133 else 1134 throw new NoSuchElementException(); 1135 } 1136 1137 public boolean hasPrevious() { 1138 return previousIndex() >= 0; 1139 } 1140 1141 public E previous() { 1142 if (hasPrevious()) 1143 return i.previous(); 1144 else 1145 throw new NoSuchElementException(); 1146 } 1147 1148 public int nextIndex() { 1149 return i.nextIndex() - offset; 1150 } 1151 1152 public int previousIndex() { 1153 return i.previousIndex() - offset; 1154 } 1155 1156 public void remove() { 1157 throw new UnsupportedOperationException (); 1158 } 1159 1160 public void set(E o) { 1161 throw new UnsupportedOperationException (); 1162 } 1163 1164 public void add(E o) { 1165 throw new UnsupportedOperationException (); 1166 } 1167 } 1168 1169} 1170 | Popular Tags |