1 24 25 package EDU.oswego.cs.dl.util.concurrent; 26 import java.util.*; 27 28 80 81 82 public class CopyOnWriteArrayList implements List, Cloneable , java.io.Serializable { 83 87 88 protected transient Object [] array_; 89 90 94 protected synchronized Object [] array() { return array_; } 95 96 100 public CopyOnWriteArrayList() { 101 array_ = new Object [0]; 102 } 103 104 109 public CopyOnWriteArrayList(Collection c) { 110 array_ = new Object [c.size()]; 111 Iterator i = c.iterator(); 112 int size = 0; 113 while (i.hasNext()) 114 array_[size++] = i.next(); 115 } 116 117 122 public CopyOnWriteArrayList(Object [] toCopyIn) { 123 copyIn(toCopyIn, 0, toCopyIn.length); 124 } 125 126 138 public synchronized void copyIn(Object [] toCopyIn, int first, int n) { 139 array_ = new Object [n]; 140 System.arraycopy(toCopyIn, first, array_, 0, n); 141 } 142 143 148 public int size() { 149 return array().length; 150 } 151 152 158 public boolean isEmpty() { 159 return size() == 0; 160 } 161 162 167 public boolean contains(Object elem) { 168 Object [] elementData = array(); 169 int len = elementData.length; 170 return indexOf(elem, elementData, len) >= 0; 171 } 172 173 182 public int indexOf(Object elem) { 183 Object [] elementData = array(); 184 int len = elementData.length; 185 return indexOf(elem, elementData, len); 186 } 187 188 189 193 194 protected static int indexOf(Object elem, 195 Object [] elementData, 196 int len) { 197 if (elem == null) { 198 for (int i = 0; i < len; i++) 199 if (elementData[i]==null) 200 return i; 201 } else { 202 for (int i = 0; i < len; i++) 203 if (elem.equals(elementData[i])) 204 return i; 205 } 206 return -1; 207 } 208 209 221 222 public int indexOf(Object elem, int index) { 224 Object [] elementData = array(); 225 int elementCount = elementData.length; 226 227 if (elem == null) { 228 for (int i = index ; i < elementCount ; i++) 229 if (elementData[i]==null) 230 return i; 231 } else { 232 for (int i = index ; i < elementCount ; i++) 233 if (elem.equals(elementData[i])) 234 return i; 235 } 236 return -1; 237 } 238 239 247 public int lastIndexOf(Object elem) { 248 Object [] elementData = array(); 249 int len = elementData.length; 250 return lastIndexOf(elem, elementData, len); 251 } 252 253 protected static int lastIndexOf(Object elem, 254 Object [] elementData, 255 int len) { 256 if (elem == null) { 257 for (int i = len-1; i >= 0; i--) 258 if (elementData[i]==null) 259 return i; 260 } else { 261 for (int i = len-1; i >= 0; i--) 262 if (elem.equals(elementData[i])) 263 return i; 264 } 265 return -1; 266 } 267 268 278 279 public int lastIndexOf(Object elem, int index) { 280 Object [] elementData = array(); 282 if (elem == null) { 283 for (int i = index; i >= 0; i--) 284 if (elementData[i]==null) 285 return i; 286 } else { 287 for (int i = index; i >= 0; i--) 288 if (elem.equals(elementData[i])) 289 return i; 290 } 291 return -1; 292 } 293 294 300 public Object clone() { 301 try { 302 Object [] elementData = array(); 303 CopyOnWriteArrayList v = (CopyOnWriteArrayList)super.clone(); 304 v.array_ = new Object [elementData.length]; 305 System.arraycopy(elementData, 0, v.array_, 0, elementData.length); 306 return v; 307 } catch (CloneNotSupportedException e) { 308 throw new InternalError (); 310 } 311 } 312 313 317 public Object [] toArray() { 318 Object [] elementData = array(); 319 Object [] result = new Object [elementData.length]; 320 System.arraycopy(elementData, 0, result, 0, elementData.length); 321 return result; 322 } 323 324 345 public Object [] toArray(Object a[]) { 346 Object [] elementData = array(); 347 348 if (a.length < elementData.length) 349 a = (Object []) 350 java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), 351 elementData.length); 352 353 System.arraycopy(elementData, 0, a, 0, elementData.length); 354 355 if (a.length > elementData.length) 356 a[elementData.length] = null; 357 358 return a; 359 } 360 361 363 370 public Object get(int index) { 371 Object [] elementData = array(); 372 rangeCheck(index, elementData.length); 373 return elementData[index]; 374 } 375 376 386 public synchronized Object set(int index, Object element) { 387 int len = array_.length; 388 rangeCheck(index, len); 389 Object oldValue = array_[index]; 390 391 boolean same = (oldValue == element || 392 (element != null && element.equals(oldValue))); 393 if (!same) { 394 Object [] newArray = new Object [len]; 395 System.arraycopy(array_, 0, newArray, 0, len); 396 newArray[index] = element; 397 array_ = newArray; 398 } 399 return oldValue; 400 } 401 402 408 public synchronized boolean add(Object element) { 409 int len = array_.length; 410 Object [] newArray = new Object [len+1]; 411 System.arraycopy(array_, 0, newArray, 0, len); 412 newArray[len] = element; 413 array_ = newArray; 414 return true; 415 } 416 417 427 public synchronized void add(int index, Object element) { 428 int len = array_.length; 429 if (index > len || index < 0) 430 throw new IndexOutOfBoundsException ("Index: "+index+", Size: "+len); 431 432 Object [] newArray = new Object [len+1]; 433 System.arraycopy(array_, 0, newArray, 0, index); 434 newArray[index] = element; 435 System.arraycopy(array_, index, newArray, index+1, len - index); 436 array_ = newArray; 437 } 438 439 448 public synchronized Object remove(int index) { 449 int len = array_.length; 450 rangeCheck(index, len); 451 Object oldValue = array_[index]; 452 Object [] newArray = new Object [len-1]; 453 System.arraycopy(array_, 0, newArray, 0, index); 454 int numMoved = len - index - 1; 455 if (numMoved > 0) 456 System.arraycopy(array_, index+1, newArray, index, numMoved); 457 array_ = newArray; 458 return oldValue; 459 } 460 461 473 public synchronized boolean remove(Object element) { 474 int len = array_.length; 475 if (len == 0) return false; 476 477 480 int newlen = len-1; 481 Object [] newArray = new Object [newlen]; 482 483 for (int i = 0; i < newlen; ++i) { 484 if (element == array_[i] || 485 (element != null && element.equals(array_[i]))) { 486 for (int k = i + 1; k < len; ++k) newArray[k-1] = array_[k]; 488 array_ = newArray; 489 return true; 490 } 491 else 492 newArray[i] = array_[i]; 493 } 494 496 if (element == array_[newlen] || 497 (element != null && element.equals(array_[newlen]))) { 498 array_ = newArray; 499 return true; 500 } 501 else 502 return false; 504 } 505 506 507 520 public synchronized void removeRange(int fromIndex, int toIndex) { 521 int len = array_.length; 522 523 if (fromIndex < 0 || fromIndex >= len || 524 toIndex > len || toIndex < fromIndex) 525 throw new IndexOutOfBoundsException (); 526 527 int numMoved = len - toIndex; 528 int newlen = len - (toIndex-fromIndex); 529 Object [] newArray = new Object [newlen]; 530 System.arraycopy(array_, 0, newArray, 0, fromIndex); 531 System.arraycopy(array_, toIndex, newArray, fromIndex, numMoved); 532 array_ = newArray; 533 } 534 535 536 543 public synchronized boolean addIfAbsent(Object element) { 544 int len = array_.length; 547 Object [] newArray = new Object [len + 1]; 548 for (int i = 0; i < len; ++i) { 549 if (element == array_[i] || 550 (element != null && element.equals(array_[i]))) 551 return false; else 553 newArray[i] = array_[i]; 554 } 555 newArray[len] = element; 556 array_ = newArray; 557 return true; 558 } 559 560 570 public boolean containsAll(Collection c) { 571 Object [] elementData = array(); 572 int len = elementData.length; 573 Iterator e = c.iterator(); 574 while (e.hasNext()) 575 if(indexOf(e.next(), elementData, len) < 0) 576 return false; 577 578 return true; 579 } 580 581 582 590 public synchronized boolean removeAll(Collection c) { 591 Object [] elementData = array_; 592 int len = elementData.length; 593 if (len == 0) return false; 594 595 Object [] temp = new Object [len]; 597 int newlen = 0; 598 for (int i = 0; i < len; ++i) { 599 Object element = elementData[i]; 600 if (!c.contains(element)) { 601 temp[newlen++] = element; 602 } 603 } 604 605 if (newlen == len) return false; 606 607 Object [] newArray = new Object [newlen]; 609 System.arraycopy(temp, 0, newArray, 0, newlen); 610 array_ = newArray; 611 return true; 612 } 613 614 621 public synchronized boolean retainAll(Collection c) { 622 Object [] elementData = array_; 623 int len = elementData.length; 624 if (len == 0) return false; 625 626 Object [] temp = new Object [len]; 627 int newlen = 0; 628 for (int i = 0; i < len; ++i) { 629 Object element = elementData[i]; 630 if (c.contains(element)) { 631 temp[newlen++] = element; 632 } 633 } 634 635 if (newlen == len) return false; 636 637 Object [] newArray = new Object [newlen]; 638 System.arraycopy(temp, 0, newArray, 0, newlen); 639 array_ = newArray; 640 return true; 641 } 642 643 652 653 public synchronized int addAllAbsent(Collection c) { 654 int numNew = c.size(); 655 if (numNew == 0) return 0; 656 657 Object [] elementData = array_; 658 int len = elementData.length; 659 660 Object [] temp = new Object [numNew]; 661 int added = 0; 662 Iterator e = c.iterator(); 663 while (e.hasNext()) { 664 Object element = e.next(); 665 if (indexOf(element, elementData, len) < 0) { 666 if (indexOf(element, temp, added) < 0) { 667 temp[added++] = element; 668 } 669 } 670 } 671 672 if (added == 0) return 0; 673 674 Object [] newArray = new Object [len+added]; 675 System.arraycopy(elementData, 0, newArray, 0, len); 676 System.arraycopy(temp, 0, newArray, len, added); 677 array_ = newArray; 678 return added; 679 } 680 681 685 public synchronized void clear() { 686 array_ = new Object [0]; 687 } 688 689 696 public synchronized boolean addAll(Collection c) { 697 int numNew = c.size(); 698 if (numNew == 0) return false; 699 700 int len = array_.length; 701 Object [] newArray = new Object [len+numNew]; 702 System.arraycopy(array_, 0, newArray, 0, len); 703 Iterator e = c.iterator(); 704 for (int i=0; i<numNew; i++) 705 newArray[len++] = e.next(); 706 array_ = newArray; 707 708 return true; 709 } 710 711 725 public synchronized boolean addAll(int index, Collection c) { 726 int len = array_.length; 727 if (index > len || index < 0) 728 throw new IndexOutOfBoundsException ("Index: "+index+", Size: "+len); 729 730 int numNew = c.size(); 731 if (numNew == 0) return false; 732 733 Object [] newArray = new Object [len+numNew]; 734 System.arraycopy(array_, 0, newArray, 0, len); 735 int numMoved = len - index; 736 if (numMoved > 0) 737 System.arraycopy(array_, index, newArray, index + numNew, numMoved); 738 Iterator e = c.iterator(); 739 for (int i=0; i<numNew; i++) 740 newArray[index++] = e.next(); 741 array_ = newArray; 742 743 return true; 744 } 745 746 750 protected void rangeCheck(int index, int length) { 751 if (index >= length || index < 0) 752 throw new IndexOutOfBoundsException ("Index: "+index+", Size: "+ length); 753 } 754 761 private void writeObject(java.io.ObjectOutputStream s) 762 throws java.io.IOException { 763 s.defaultWriteObject(); 765 766 Object [] elementData = array(); 767 s.writeInt(elementData.length); 769 770 for (int i=0; i<elementData.length; i++) 772 s.writeObject(elementData[i]); 773 } 774 775 778 private synchronized void readObject(java.io.ObjectInputStream s) 779 throws java.io.IOException , ClassNotFoundException { 780 s.defaultReadObject(); 782 783 int arrayLength = s.readInt(); 785 Object [] elementData = new Object [arrayLength]; 786 787 for (int i=0; i<elementData.length; i++) 789 elementData[i] = s.readObject(); 790 array_ = elementData; 791 } 792 793 797 public String toString() { 798 StringBuffer buf = new StringBuffer (); 799 Iterator e = iterator(); 800 buf.append("["); 801 int maxIndex = size() - 1; 802 for (int i = 0; i <= maxIndex; i++) { 803 buf.append(String.valueOf(e.next())); 804 if (i < maxIndex) 805 buf.append(", "); 806 } 807 buf.append("]"); 808 return buf.toString(); 809 } 810 811 812 833 public boolean equals(Object o) { 834 if (o == this) 835 return true; 836 if (!(o instanceof List)) 837 return false; 838 839 List l2 = (List)(o); 840 if (size() != l2.size()) 841 return false; 842 843 ListIterator e1 = listIterator(); 844 ListIterator e2 = l2.listIterator(); 845 while(e1.hasNext()) { 846 Object o1 = e1.next(); 847 Object o2 = e2.next(); 848 if (!(o1==null ? o2==null : o1.equals(o2))) 849 return false; 850 } 851 return true; 852 } 853 854 860 public int hashCode() { 861 int hashCode = 1; 862 Iterator i = iterator(); 863 while (i.hasNext()) { 864 Object obj = i.next(); 865 hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode()); 866 } 867 return hashCode; 868 } 869 870 877 public Iterator iterator() { 878 return new COWIterator(array(), 0); 879 } 880 881 890 891 public ListIterator listIterator() { 892 return new COWIterator(array(), 0); 893 } 894 895 910 public ListIterator listIterator(final int index) { 911 Object [] elementData = array(); 912 int len = elementData.length; 913 if (index<0 || index>len) 914 throw new IndexOutOfBoundsException ("Index: "+index); 915 916 return new COWIterator(array(), index); 917 } 918 919 protected static class COWIterator implements ListIterator { 920 921 922 protected final Object [] array; 923 924 927 protected int cursor; 928 929 protected COWIterator(Object [] elementArray, int initialCursor) { 930 array = elementArray; 931 cursor = initialCursor; 932 } 933 934 public boolean hasNext() { 935 return cursor < array.length; 936 } 937 938 public boolean hasPrevious() { 939 return cursor > 0; 940 } 941 942 public Object next() { 943 try { 944 return array[cursor++]; 945 } 946 catch (IndexOutOfBoundsException ex) { 947 throw new NoSuchElementException(); 948 } 949 } 950 951 public Object previous() { 952 try { 953 return array[--cursor]; 954 } catch(IndexOutOfBoundsException e) { 955 throw new NoSuchElementException(); 956 } 957 } 958 959 public int nextIndex() { 960 return cursor; 961 } 962 963 public int previousIndex() { 964 return cursor-1; 965 } 966 967 972 973 public void remove() { 974 throw new UnsupportedOperationException (); 975 } 976 977 982 public void set(Object o) { 983 throw new UnsupportedOperationException (); 984 } 985 986 991 public void add(Object o) { 992 throw new UnsupportedOperationException (); 993 } 994 } 995 996 997 1016 public synchronized List subList(int fromIndex, int toIndex) { 1017 int len = array_.length; 1019 if (fromIndex<0 || toIndex>len || fromIndex>toIndex) 1020 throw new IndexOutOfBoundsException (); 1021 return new COWSubList(this, fromIndex, toIndex); 1022 } 1023 1024 protected static class COWSubList extends AbstractList { 1025 1026 1045 1046 protected final CopyOnWriteArrayList l; 1047 protected final int offset; 1048 protected int size; 1049 protected Object [] expectedArray; 1050 1051 protected COWSubList(CopyOnWriteArrayList list, 1052 int fromIndex, int toIndex) { 1053 l = list; 1054 expectedArray = l.array(); 1055 offset = fromIndex; 1056 size = toIndex - fromIndex; 1057 } 1058 1059 protected void checkForComodification() { 1061 if (l.array_ != expectedArray) 1062 throw new ConcurrentModificationException(); 1063 } 1064 1065 protected void rangeCheck(int index) { 1067 if (index<0 || index>=size) 1068 throw new IndexOutOfBoundsException ("Index: "+index+ 1069 ",Size: "+size); 1070 } 1071 1072 1073 public Object set(int index, Object element) { 1074 synchronized(l) { 1075 rangeCheck(index); 1076 checkForComodification(); 1077 Object x = l.set(index+offset, element); 1078 expectedArray = l.array_; 1079 return x; 1080 } 1081 } 1082 1083 public Object get(int index) { 1084 synchronized(l) { 1085 rangeCheck(index); 1086 checkForComodification(); 1087 return l.get(index+offset); 1088 } 1089 } 1090 1091 public int size() { 1092 synchronized(l) { 1093 checkForComodification(); 1094 return size; 1095 } 1096 } 1097 1098 public void add(int index, Object element) { 1099 synchronized(l) { 1100 checkForComodification(); 1101 if (index<0 || index>size) 1102 throw new IndexOutOfBoundsException (); 1103 l.add(index+offset, element); 1104 expectedArray = l.array_; 1105 size++; 1106 } 1107 } 1108 1109 public Object remove(int index) { 1110 synchronized(l) { 1111 rangeCheck(index); 1112 checkForComodification(); 1113 Object result = l.remove(index+offset); 1114 expectedArray = l.array_; 1115 size--; 1116 return result; 1117 } 1118 } 1119 1120 public Iterator iterator() { 1121 synchronized(l) { 1122 checkForComodification(); 1123 return new COWSubListIterator(0); 1124 } 1125 } 1126 1127 public ListIterator listIterator(final int index) { 1128 synchronized(l) { 1129 checkForComodification(); 1130 if (index<0 || index>size) 1131 throw new IndexOutOfBoundsException ("Index: "+index+", Size: "+size); 1132 return new COWSubListIterator(index); 1133 } 1134 } 1135 1136 protected class COWSubListIterator implements ListIterator { 1137 protected final ListIterator i; 1138 protected final int index; 1139 protected COWSubListIterator(int index) { 1140 this.index = index; 1141 i = l.listIterator(index+offset); 1142 } 1143 1144 public boolean hasNext() { 1145 return nextIndex() < size; 1146 } 1147 1148 public Object next() { 1149 if (hasNext()) 1150 return i.next(); 1151 else 1152 throw new NoSuchElementException(); 1153 } 1154 1155 public boolean hasPrevious() { 1156 return previousIndex() >= 0; 1157 } 1158 1159 public Object previous() { 1160 if (hasPrevious()) 1161 return i.previous(); 1162 else 1163 throw new NoSuchElementException(); 1164 } 1165 1166 public int nextIndex() { 1167 return i.nextIndex() - offset; 1168 } 1169 1170 public int previousIndex() { 1171 return i.previousIndex() - offset; 1172 } 1173 1174 public void remove() { 1175 throw new UnsupportedOperationException (); 1176 } 1177 1178 public void set(Object o) { 1179 throw new UnsupportedOperationException (); 1180 } 1181 1182 public void add(Object o) { 1183 throw new UnsupportedOperationException (); 1184 } 1185 } 1186 1187 1188 public List subList(int fromIndex, int toIndex) { 1189 synchronized(l) { 1190 checkForComodification(); 1191 if (fromIndex<0 || toIndex>size) 1192 throw new IndexOutOfBoundsException (); 1193 return new COWSubList(l, fromIndex+offset, toIndex+offset); 1194 } 1195 } 1196 1197 1198 } 1199 1200} 1201 | Popular Tags |