1 16 package org.apache.commons.collections.list; 17 18 import java.io.IOException ; 19 import java.io.ObjectInputStream ; 20 import java.io.ObjectOutputStream ; 21 import java.lang.reflect.Array ; 22 import java.util.AbstractList ; 23 import java.util.Collection ; 24 import java.util.ConcurrentModificationException ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.ListIterator ; 28 import java.util.NoSuchElementException ; 29 30 import org.apache.commons.collections.OrderedIterator; 31 32 47 public abstract class AbstractLinkedList implements List { 48 49 59 60 65 protected transient Node header; 66 67 protected transient int size; 68 69 protected transient int modCount; 70 71 77 protected AbstractLinkedList() { 78 super(); 79 } 80 81 86 protected AbstractLinkedList(Collection coll) { 87 super(); 88 init(); 89 addAll(coll); 90 } 91 92 98 protected void init() { 99 header = createHeaderNode(); 100 } 101 102 public int size() { 104 return size; 105 } 106 107 public boolean isEmpty() { 108 return (size() == 0); 109 } 110 111 public Object get(int index) { 112 Node node = getNode(index, false); 113 return node.getValue(); 114 } 115 116 public Iterator iterator() { 118 return listIterator(); 119 } 120 121 public ListIterator listIterator() { 122 return new LinkedListIterator(this, 0); 123 } 124 125 public ListIterator listIterator(int fromIndex) { 126 return new LinkedListIterator(this, fromIndex); 127 } 128 129 public int indexOf(Object value) { 131 int i = 0; 132 for (Node node = header.next; node != header; node = node.next) { 133 if (isEqualValue(node.getValue(), value)) { 134 return i; 135 } 136 i++; 137 } 138 return -1; 139 } 140 141 public int lastIndexOf(Object value) { 142 int i = size - 1; 143 for (Node node = header.previous; node != header; node = node.previous) { 144 if (isEqualValue(node.getValue(), value)) { 145 return i; 146 } 147 i--; 148 } 149 return -1; 150 } 151 152 public boolean contains(Object value) { 153 return indexOf(value) != -1; 154 } 155 156 public boolean containsAll(Collection coll) { 157 Iterator it = coll.iterator(); 158 while (it.hasNext()) { 159 if (contains(it.next()) == false) { 160 return false; 161 } 162 } 163 return true; 164 } 165 166 public Object [] toArray() { 168 return toArray(new Object [size]); 169 } 170 171 public Object [] toArray(Object [] array) { 172 if (array.length < size) { 174 Class componentType = array.getClass().getComponentType(); 175 array = (Object []) Array.newInstance(componentType, size); 176 } 177 int i = 0; 179 for (Node node = header.next; node != header; node = node.next, i++) { 180 array[i] = node.getValue(); 181 } 182 if (array.length > size) { 184 array[size] = null; 185 } 186 return array; 187 } 188 189 196 public List subList(int fromIndexInclusive, int toIndexExclusive) { 197 return new LinkedSubList(this, fromIndexInclusive, toIndexExclusive); 198 } 199 200 public boolean add(Object value) { 202 addLast(value); 203 return true; 204 } 205 206 public void add(int index, Object value) { 207 Node node = getNode(index, true); 208 addNodeBefore(node, value); 209 } 210 211 public boolean addAll(Collection coll) { 212 return addAll(size, coll); 213 } 214 215 public boolean addAll(int index, Collection coll) { 216 Node node = getNode(index, true); 217 for (Iterator itr = coll.iterator(); itr.hasNext();) { 218 Object value = itr.next(); 219 addNodeBefore(node, value); 220 } 221 return true; 222 } 223 224 public Object remove(int index) { 226 Node node = getNode(index, false); 227 Object oldValue = node.getValue(); 228 removeNode(node); 229 return oldValue; 230 } 231 232 public boolean remove(Object value) { 233 for (Node node = header.next; node != header; node = node.next) { 234 if (isEqualValue(node.getValue(), value)) { 235 removeNode(node); 236 return true; 237 } 238 } 239 return false; 240 } 241 242 public boolean removeAll(Collection coll) { 243 boolean modified = false; 244 Iterator it = iterator(); 245 while (it.hasNext()) { 246 if (coll.contains(it.next())) { 247 it.remove(); 248 modified = true; 249 } 250 } 251 return modified; 252 } 253 254 public boolean retainAll(Collection coll) { 256 boolean modified = false; 257 Iterator it = iterator(); 258 while (it.hasNext()) { 259 if (coll.contains(it.next()) == false) { 260 it.remove(); 261 modified = true; 262 } 263 } 264 return modified; 265 } 266 267 public Object set(int index, Object value) { 268 Node node = getNode(index, false); 269 Object oldValue = node.getValue(); 270 updateNode(node, value); 271 return oldValue; 272 } 273 274 public void clear() { 275 removeAllNodes(); 276 } 277 278 public Object getFirst() { 280 Node node = header.next; 281 if (node == header) { 282 throw new NoSuchElementException (); 283 } 284 return node.getValue(); 285 } 286 287 public Object getLast() { 288 Node node = header.previous; 289 if (node == header) { 290 throw new NoSuchElementException (); 291 } 292 return node.getValue(); 293 } 294 295 public boolean addFirst(Object o) { 296 addNodeAfter(header, o); 297 return true; 298 } 299 300 public boolean addLast(Object o) { 301 addNodeBefore(header, o); 302 return true; 303 } 304 305 public Object removeFirst() { 306 Node node = header.next; 307 if (node == header) { 308 throw new NoSuchElementException (); 309 } 310 Object oldValue = node.getValue(); 311 removeNode(node); 312 return oldValue; 313 } 314 315 public Object removeLast() { 316 Node node = header.previous; 317 if (node == header) { 318 throw new NoSuchElementException (); 319 } 320 Object oldValue = node.getValue(); 321 removeNode(node); 322 return oldValue; 323 } 324 325 public boolean equals(Object obj) { 327 if (obj == this) { 328 return true; 329 } 330 if (obj instanceof List == false) { 331 return false; 332 } 333 List other = (List ) obj; 334 if (other.size() != size()) { 335 return false; 336 } 337 ListIterator it1 = listIterator(); 338 ListIterator it2 = other.listIterator(); 339 while (it1.hasNext() && it2.hasNext()) { 340 Object o1 = it1.next(); 341 Object o2 = it2.next(); 342 if (!(o1 == null ? o2 == null : o1.equals(o2))) 343 return false; 344 } 345 return !(it1.hasNext() || it2.hasNext()); 346 } 347 348 public int hashCode() { 349 int hashCode = 1; 350 Iterator it = iterator(); 351 while (it.hasNext()) { 352 Object obj = it.next(); 353 hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode()); 354 } 355 return hashCode; 356 } 357 358 public String toString() { 359 if (size() == 0) { 360 return "[]"; 361 } 362 StringBuffer buf = new StringBuffer (16 * size()); 363 buf.append("["); 364 365 Iterator it = iterator(); 366 boolean hasNext = it.hasNext(); 367 while (hasNext) { 368 Object value = it.next(); 369 buf.append(value == this ? "(this Collection)" : value); 370 hasNext = it.hasNext(); 371 if (hasNext) { 372 buf.append(", "); 373 } 374 } 375 buf.append("]"); 376 return buf.toString(); 377 } 378 379 389 protected boolean isEqualValue(Object value1, Object value2) { 390 return (value1 == value2 || (value1 == null ? false : value1.equals(value2))); 391 } 392 393 401 protected void updateNode(Node node, Object value) { 402 node.setValue(value); 403 } 404 405 412 protected Node createHeaderNode() { 413 return new Node(); 414 } 415 416 423 protected Node createNode(Object value) { 424 return new Node(value); 425 } 426 427 438 protected void addNodeBefore(Node node, Object value) { 439 Node newNode = createNode(value); 440 addNode(newNode, node); 441 } 442 443 454 protected void addNodeAfter(Node node, Object value) { 455 Node newNode = createNode(value); 456 addNode(newNode, node.next); 457 } 458 459 466 protected void addNode(Node nodeToInsert, Node insertBeforeNode) { 467 nodeToInsert.next = insertBeforeNode; 468 nodeToInsert.previous = insertBeforeNode.previous; 469 insertBeforeNode.previous.next = nodeToInsert; 470 insertBeforeNode.previous = nodeToInsert; 471 size++; 472 modCount++; 473 } 474 475 481 protected void removeNode(Node node) { 482 node.previous.next = node.next; 483 node.next.previous = node.previous; 484 size--; 485 modCount++; 486 } 487 488 491 protected void removeAllNodes() { 492 header.next = header; 493 header.previous = header; 494 size = 0; 495 modCount++; 496 } 497 498 508 protected Node getNode(int index, boolean endMarkerAllowed) throws IndexOutOfBoundsException { 509 if (index < 0) { 511 throw new IndexOutOfBoundsException ("Couldn't get the node: " + 512 "index (" + index + ") less than zero."); 513 } 514 if (!endMarkerAllowed && index == size) { 515 throw new IndexOutOfBoundsException ("Couldn't get the node: " + 516 "index (" + index + ") is the size of the list."); 517 } 518 if (index > size) { 519 throw new IndexOutOfBoundsException ("Couldn't get the node: " + 520 "index (" + index + ") greater than the size of the " + 521 "list (" + size + ")."); 522 } 523 Node node; 525 if (index < (size / 2)) { 526 node = header.next; 528 for (int currentIndex = 0; currentIndex < index; currentIndex++) { 529 node = node.next; 530 } 531 } else { 532 node = header; 534 for (int currentIndex = size; currentIndex > index; currentIndex--) { 535 node = node.previous; 536 } 537 } 538 return node; 539 } 540 541 547 protected Iterator createSubListIterator(LinkedSubList subList) { 548 return createSubListListIterator(subList, 0); 549 } 550 551 557 protected ListIterator createSubListListIterator(LinkedSubList subList, int fromIndex) { 558 return new LinkedSubListIterator(subList, fromIndex); 559 } 560 561 568 protected void doWriteObject(ObjectOutputStream outputStream) throws IOException { 569 outputStream.writeInt(size()); 571 for (Iterator itr = iterator(); itr.hasNext();) { 572 outputStream.writeObject(itr.next()); 573 } 574 } 575 576 582 protected void doReadObject(ObjectInputStream inputStream) throws IOException , ClassNotFoundException { 583 init(); 584 int size = inputStream.readInt(); 585 for (int i = 0; i < size; i++) { 586 add(inputStream.readObject()); 587 } 588 } 589 590 597 protected static class Node { 598 599 600 protected Node previous; 601 602 protected Node next; 603 604 protected Object value; 605 606 609 protected Node() { 610 super(); 611 previous = this; 612 next = this; 613 } 614 615 620 protected Node(Object value) { 621 super(); 622 this.value = value; 623 } 624 625 632 protected Node(Node previous, Node next, Object value) { 633 super(); 634 this.previous = previous; 635 this.next = next; 636 this.value = value; 637 } 638 639 645 protected Object getValue() { 646 return value; 647 } 648 649 655 protected void setValue(Object value) { 656 this.value = value; 657 } 658 659 665 protected Node getPreviousNode() { 666 return previous; 667 } 668 669 675 protected void setPreviousNode(Node previous) { 676 this.previous = previous; 677 } 678 679 685 protected Node getNextNode() { 686 return next; 687 } 688 689 695 protected void setNextNode(Node next) { 696 this.next = next; 697 } 698 } 699 700 704 protected static class LinkedListIterator implements ListIterator , OrderedIterator { 705 706 707 protected final AbstractLinkedList parent; 708 709 713 protected Node next; 714 715 718 protected int nextIndex; 719 720 728 protected Node current; 729 730 736 protected int expectedModCount; 737 738 744 protected LinkedListIterator(AbstractLinkedList parent, int fromIndex) throws IndexOutOfBoundsException { 745 super(); 746 this.parent = parent; 747 this.expectedModCount = parent.modCount; 748 this.next = parent.getNode(fromIndex, true); 749 this.nextIndex = fromIndex; 750 } 751 752 759 protected void checkModCount() { 760 if (parent.modCount != expectedModCount) { 761 throw new ConcurrentModificationException (); 762 } 763 } 764 765 772 protected Node getLastNodeReturned() throws IllegalStateException { 773 if (current == null) { 774 throw new IllegalStateException (); 775 } 776 return current; 777 } 778 779 public boolean hasNext() { 780 return next != parent.header; 781 } 782 783 public Object next() { 784 checkModCount(); 785 if (!hasNext()) { 786 throw new NoSuchElementException ("No element at index " + nextIndex + "."); 787 } 788 Object value = next.getValue(); 789 current = next; 790 next = next.next; 791 nextIndex++; 792 return value; 793 } 794 795 public boolean hasPrevious() { 796 return next.previous != parent.header; 797 } 798 799 public Object previous() { 800 checkModCount(); 801 if (!hasPrevious()) { 802 throw new NoSuchElementException ("Already at start of list."); 803 } 804 next = next.previous; 805 Object value = next.getValue(); 806 current = next; 807 nextIndex--; 808 return value; 809 } 810 811 public int nextIndex() { 812 return nextIndex; 813 } 814 815 public int previousIndex() { 816 return nextIndex() - 1; 818 } 819 820 public void remove() { 821 checkModCount(); 822 parent.removeNode(getLastNodeReturned()); 823 current = null; 824 nextIndex--; 825 expectedModCount++; 826 } 827 828 public void set(Object obj) { 829 checkModCount(); 830 getLastNodeReturned().setValue(obj); 831 } 832 833 public void add(Object obj) { 834 checkModCount(); 835 parent.addNodeBefore(next, obj); 836 current = null; 837 nextIndex++; 838 expectedModCount++; 839 } 840 841 } 842 843 847 protected static class LinkedSubListIterator extends LinkedListIterator { 848 849 850 protected final LinkedSubList sub; 851 852 protected LinkedSubListIterator(LinkedSubList sub, int startIndex) { 853 super(sub.parent, startIndex + sub.offset); 854 this.sub = sub; 855 } 856 857 public boolean hasNext() { 858 return (nextIndex() < sub.size); 859 } 860 861 public boolean hasPrevious() { 862 return (previousIndex() >= 0); 863 } 864 865 public int nextIndex() { 866 return (super.nextIndex() - sub.offset); 867 } 868 869 public void add(Object obj) { 870 super.add(obj); 871 sub.expectedModCount = parent.modCount; 872 sub.size++; 873 } 874 875 public void remove() { 876 super.remove(); 877 sub.expectedModCount = parent.modCount; 878 sub.size--; 879 } 880 } 881 882 886 protected static class LinkedSubList extends AbstractList { 887 888 private AbstractLinkedList parent; 889 890 private int offset; 891 892 private int size; 893 894 private int expectedModCount; 895 896 protected LinkedSubList(AbstractLinkedList parent, int fromIndex, int toIndex) { 897 if (fromIndex < 0) { 898 throw new IndexOutOfBoundsException ("fromIndex = " + fromIndex); 899 } 900 if (toIndex > parent.size()) { 901 throw new IndexOutOfBoundsException ("toIndex = " + toIndex); 902 } 903 if (fromIndex > toIndex) { 904 throw new IllegalArgumentException ("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); 905 } 906 this.parent = parent; 907 this.offset = fromIndex; 908 this.size = toIndex - fromIndex; 909 this.expectedModCount = parent.modCount; 910 } 911 912 public int size() { 913 checkModCount(); 914 return size; 915 } 916 917 public Object get(int index) { 918 rangeCheck(index, size); 919 checkModCount(); 920 return parent.get(index + offset); 921 } 922 923 public void add(int index, Object obj) { 924 rangeCheck(index, size + 1); 925 checkModCount(); 926 parent.add(index + offset, obj); 927 expectedModCount = parent.modCount; 928 size++; 929 LinkedSubList.this.modCount++; 930 } 931 932 public Object remove(int index) { 933 rangeCheck(index, size); 934 checkModCount(); 935 Object result = parent.remove(index + offset); 936 expectedModCount = parent.modCount; 937 size--; 938 LinkedSubList.this.modCount++; 939 return result; 940 } 941 942 public boolean addAll(Collection coll) { 943 return addAll(size, coll); 944 } 945 946 public boolean addAll(int index, Collection coll) { 947 rangeCheck(index, size + 1); 948 int cSize = coll.size(); 949 if (cSize == 0) { 950 return false; 951 } 952 953 checkModCount(); 954 parent.addAll(offset + index, coll); 955 expectedModCount = parent.modCount; 956 size += cSize; 957 LinkedSubList.this.modCount++; 958 return true; 959 } 960 961 public Object set(int index, Object obj) { 962 rangeCheck(index, size); 963 checkModCount(); 964 return parent.set(index + offset, obj); 965 } 966 967 public void clear() { 968 checkModCount(); 969 Iterator it = iterator(); 970 while (it.hasNext()) { 971 it.next(); 972 it.remove(); 973 } 974 } 975 976 public Iterator iterator() { 977 checkModCount(); 978 return parent.createSubListIterator(this); 979 } 980 981 public ListIterator listIterator(final int index) { 982 rangeCheck(index, size + 1); 983 checkModCount(); 984 return parent.createSubListListIterator(this, index); 985 } 986 987 public List subList(int fromIndexInclusive, int toIndexExclusive) { 988 return new LinkedSubList(parent, fromIndexInclusive + offset, toIndexExclusive + offset); 989 } 990 991 protected void rangeCheck(int index, int beyond) { 992 if (index < 0 || index >= beyond) { 993 throw new IndexOutOfBoundsException ("Index '" + index + "' out of bounds for size '" + size + "'"); 994 } 995 } 996 997 protected void checkModCount() { 998 if (parent.modCount != expectedModCount) { 999 throw new ConcurrentModificationException (); 1000 } 1001 } 1002 } 1003 1004} 1005 | Popular Tags |