# HG changeset patch # User smarks # Date 1431735959 25200 # Fri May 15 17:25:59 2015 -0700 # Node ID 1e9609a97c9bd3e75ff41aabf59d2bc753b20b71 # Parent 6adfb517cd7fcf6c64fd9d639d6b03e66ca5ea92 8072726: add adapter to convert Enumeration to Iterator Reviewed-by: XXX diff --git a/src/java.base/share/classes/java/util/Enumeration.java b/src/java.base/share/classes/java/util/Enumeration.java --- a/src/java.base/share/classes/java/util/Enumeration.java +++ b/src/java.base/share/classes/java/util/Enumeration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2015, 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 @@ -76,4 +76,59 @@ * @exception NoSuchElementException if no more elements exist. */ E nextElement(); + + /** + * Returns an {@link Iterator} whose elements are the same as the + * elements of this {@code Enumeration}. The results are undefined + * if this method is called more than once, or if this Enumeration's + * other methods are called after {@code asIterator} has been called. + * + * @apiNote + * This method is intended to help adapt code that produces + * {@code Enumeration} instances to code that consumes {@code Iterator} + * or {@code Iterable} instances. For example, the + * {@link java.security.PermissionCollection PermissionCollection.elements()} + * method returns an {@code Enumeration}. This can be adapted + * for use in an enhanced-for loop as follows: + * + *
{@code
+     *     PermissionCollection pc = ... ;
+     *     Iterable permsIterable = () -> pc.elements().asIterator();
+     *     for (Permission p : permsIterable) {
+     *         doSomethingWithPermission(p);
+     *     }
+     * }
+ * + * A {@code Stream} could be created from an + * {@code Enumeration} as follows: + * + *
{@code
+     *     Stream permsStream = StreamSupport.stream(
+     *         Spliterators.spliteratorUnknownSize(
+     *             pc.elements().asIterator(),
+     *             Spliterator.ORDERED | Spliterator.IMMUTABLE),
+     *         false);
+     * }
+ * + * @implSpec + * The returned Iterator's {@link Iterator#hasNext hasNext} method calls and returns + * the value from this Enumeration's {@code hasMoreElements} method; its + * {@link Iterator#next next} method calls and returns the value from this Enumeration's + * {@code nextElement} method; and its {@link Iterator#remove remove} method throws + * {@code UnsupportedOperationException}. + * + * @return an Iterator derived from this Enumeration + * + * @since 1.9 + */ + default Iterator asIterator() { + return new Iterator() { + @Override public boolean hasNext() { + return Enumeration.this.hasMoreElements(); + } + @Override public E next() { + return Enumeration.this.nextElement(); + } + }; + } } diff --git a/src/java.base/share/classes/java/util/Iterator.java b/src/java.base/share/classes/java/util/Iterator.java --- a/src/java.base/share/classes/java/util/Iterator.java +++ b/src/java.base/share/classes/java/util/Iterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -43,6 +43,10 @@ * * Java Collections Framework. * + * @apiNote + * An {@link Enumeration} can be converted into an {@code Iterator} by + * using the {@link Enumeration#asIterator} method. + * * @param the type of elements returned by this iterator * * @author Josh Bloch diff --git a/test/java/util/Collections/EnumerationAsIterator.java b/test/java/util/Collections/EnumerationAsIterator.java new file mode 100644 --- /dev/null +++ b/test/java/util/Collections/EnumerationAsIterator.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8072726 + * @summary Tests for Enumeration-to-Iterator conversion. + * @run testng EnumerationAsIterator + */ + +import java.util.*; + +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class EnumerationAsIterator { + public void emptyHasNext() { + Iterator it = Collections.emptyEnumeration().asIterator(); + assertFalse(it.hasNext()); + } + + @Test(expectedExceptions = {NoSuchElementException.class}) + public void emptyNextThrows() { + Iterator it = Collections.emptyEnumeration().asIterator(); + Object o = it.next(); + fail("NoSuchElementException should have been thrown"); + } + + private List copy(List input) { + List output = new ArrayList<>(); + Collections.enumeration(input) + .asIterator() + .forEachRemaining(output::add); + return output; + } + + public void copyZero() { + assertEquals(copy(Collections.emptyList()), Collections.emptyList()); + } + + public void copyOne() { + assertEquals(copy(Collections.singletonList("a")), + Collections.singletonList("a")); + } + + public void copyMany() { + List input = Arrays.asList("a", "b", "c"); + assertEquals(copy(input), input); + } + + public void repeatedCalls() { + Iterator iter = new Vector<>(Arrays.asList("a", "b", "c")) + .elements().asIterator(); + assertTrue(iter.hasNext()); + assertTrue(iter.hasNext()); + assertEquals(iter.next(), "a"); + assertEquals(iter.next(), "b"); + assertEquals(iter.next(), "c"); + assertFalse(iter.hasNext()); + assertFalse(iter.hasNext()); + } +}