--- a/jdk/src/share/classes/java/util/LinkedList.java Wed Apr 17 14:39:04 2013 -0400
+++ b/jdk/src/share/classes/java/util/LinkedList.java Wed Apr 17 11:34:31 2013 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package java.util;
+import java.util.function.Consumer;
+
/**
* Doubly-linked list implementation of the {@code List} and {@code Deque}
* interfaces. Implements all optional list operations, and permits all
@@ -948,6 +950,16 @@
expectedModCount++;
}
+ public void forEachRemaining(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ while (modCount == expectedModCount && nextIndex < size) {
+ action.accept(next.item);
+ next = next.next;
+ nextIndex++;
+ }
+ checkForComodification();
+ }
+
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
@@ -1135,4 +1147,103 @@
for (int i = 0; i < size; i++)
linkLast((E)s.readObject());
}
+
+ public Spliterator<E> spliterator() {
+ return new LLSpliterator<E>(this, -1, 0);
+ }
+
+ /** A customized variant of Spliterators.IteratorSpliterator */
+ static final class LLSpliterator<E> implements Spliterator<E> {
+ static final int BATCH_UNIT = 1 << 10; // batch array size increment
+ static final int MAX_BATCH = 1 << 25; // max batch array size;
+ final LinkedList<E> list; // null OK unless traversed
+ Node<E> current; // current node; null until initialized
+ int est; // size estimate; -1 until first needed
+ int expectedModCount; // initialized when est set
+ int batch; // batch size for splits
+
+ LLSpliterator(LinkedList<E> list, int est, int expectedModCount) {
+ this.list = list;
+ this.est = est;
+ this.expectedModCount = expectedModCount;
+ }
+
+ final int getEst() {
+ int s; // force initialization
+ final LinkedList<E> lst;
+ if ((s = est) < 0) {
+ if ((lst = list) == null)
+ s = est = 0;
+ else {
+ expectedModCount = lst.modCount;
+ current = lst.first;
+ s = est = lst.size;
+ }
+ }
+ return s;
+ }
+
+ public long estimateSize() { return (long) getEst(); }
+
+ public Spliterator<E> trySplit() {
+ Node<E> p;
+ int s = getEst();
+ if (s > 1 && (p = current) != null) {
+ int n = batch + BATCH_UNIT;
+ if (n > s)
+ n = s;
+ if (n > MAX_BATCH)
+ n = MAX_BATCH;
+ Object[] a;
+ try {
+ a = new Object[n];
+ } catch (OutOfMemoryError oome) {
+ return null;
+ }
+ int j = 0;
+ do { a[j++] = p.item; } while ((p = p.next) != null && j < n);
+ current = p;
+ batch = j;
+ est = s - j;
+ return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);
+ }
+ return null;
+ }
+
+ public void forEachRemaining(Consumer<? super E> action) {
+ Node<E> p; int n;
+ if (action == null) throw new NullPointerException();
+ if ((n = getEst()) > 0 && (p = current) != null) {
+ current = null;
+ est = 0;
+ do {
+ E e = p.item;
+ p = p.next;
+ action.accept(e);
+ } while (p != null && --n > 0);
+ }
+ if (list.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ }
+
+ public boolean tryAdvance(Consumer<? super E> action) {
+ Node<E> p;
+ if (action == null) throw new NullPointerException();
+ if (getEst() > 0 && (p = current) != null) {
+ --est;
+ E e = p.item;
+ current = p.next;
+ action.accept(e);
+ if (list.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ return true;
+ }
+ return false;
+ }
+
+ public int characteristics() {
+ return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
+ }
+ }
+
}