Path: blob/master/test/jdk/java/util/Iterator/IteratorDefaults.java
41152 views
/*1* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import org.testng.annotations.Test;2425import java.lang.reflect.Constructor;26import java.util.ArrayList;27import java.util.Arrays;28import java.util.Collection;29import java.util.Collections;30import java.util.Iterator;31import java.util.List;32import java.util.ListIterator;33import java.util.NoSuchElementException;3435import static org.testng.Assert.assertEquals;36import static org.testng.Assert.assertFalse;37import static org.testng.Assert.assertTrue;38import static org.testng.Assert.fail;3940/**41* @test42* @run testng IteratorDefaults43* @summary test extension methods on Iterator44*/45@Test46public class IteratorDefaults {4748private static interface Callback {49void call(List<Integer> list);50}5152// call the callback for each recursive subList53private void trimmedSubList(final List<Integer> list, final Callback callback) {54int size = list.size();55if (size > 1) {56// trim 1 element from both ends57final List<Integer> subList = list.subList(1, size - 1);58callback.call(subList);59trimmedSubList(subList, callback);60}61}6263public void testRemoveUnsupported() {64final Iterator iterator = new Iterator() {65@Override66public boolean hasNext() {67return false;68}69@Override70public Object next() {71return null;72}73};7475try {76iterator.remove();77fail("expected UnsupportedOperationException from remove not thrown");78} catch (UnsupportedOperationException ignore) {79}80}8182public void testRemoveOverride() {83final IteratorWithRemove iterator = new IteratorWithRemove();84iterator.remove();85assertTrue(iterator.removed);86}8788public void testForEach() throws Exception {89final Integer[] data = new Integer[1000];90for (int i=0; i < data.length; i++) {91data[i] = i;92}93final List<Integer> source = Arrays.asList(data);9495final String[] iterableCollectionClasses = {96"java.util.ArrayDeque",97"java.util.ArrayList",98"java.util.HashSet",99"java.util.LinkedHashSet",100"java.util.LinkedList",101"java.util.PriorityQueue",102"java.util.TreeSet",103"java.util.Vector",104"java.util.concurrent.ConcurrentLinkedDeque",105"java.util.concurrent.ConcurrentLinkedQueue",106"java.util.concurrent.ConcurrentSkipListSet",107"java.util.concurrent.CopyOnWriteArrayList",108"java.util.concurrent.CopyOnWriteArraySet",109"java.util.concurrent.LinkedBlockingDeque",110"java.util.concurrent.LinkedBlockingQueue",111"java.util.concurrent.LinkedTransferQueue",112"java.util.concurrent.PriorityBlockingQueue"113};114115for (final String iterableClass : iterableCollectionClasses) {116final Iterable<Integer> iterable =117(Iterable<Integer>) Class.forName(iterableClass).newInstance();118((Collection<Integer>) iterable).addAll(source);119final Iterator<Integer> iterator = iterable.iterator();120final List<Integer> target = new ArrayList<>(source.size());121iterator.forEachRemaining(target::add);122if ("java.util.HashSet".equals(iterableClass)) {123target.sort((x, y) -> x - y);124assertEquals(target, source);125} else {126assertEquals(target, source);127}128129// verify that for an iterator that has been advanced via next(),130// forEach starts from the current location, not zero131final int OFFSET = 5;132final List<Integer> reference2 = new ArrayList<>(source).subList(OFFSET, source.size());133final List<Integer> removed2 = new ArrayList<>(OFFSET);134final Iterator<Integer> iterator2 = iterable.iterator();135for (int i=0; i < OFFSET; i++) {136// advance the iterator by OFFSET, saving iterated elements137removed2.add(iterator2.next());138}139final List<Integer> target2 = new ArrayList<>(reference2.size());140iterator2.forEachRemaining(target2::add);141if ("java.util.HashSet".equals(iterableClass)) {142assertEquals(target2.size(), reference2.size());143target2.addAll(removed2);144target2.sort((x, y) -> x - y);145assertEquals(target2, source);146assertEquals(target2.subList(OFFSET, source.size()), reference2);147} else {148assertEquals(target2, reference2);149}150}151}152153public void testForEachSubList() throws Exception {154final Integer[] data = new Integer[100];155for (int i = 0; i < data.length; i++) {156data[i] = i;157}158final List<Integer> source = Arrays.asList(data);159final String[] listClasses = {160"java.util.ArrayList",161"java.util.LinkedList",162"java.util.Vector",163"java.util.concurrent.CopyOnWriteArrayList"164};165for (final String listClass : listClasses) {166final List<Integer> list =167(List<Integer>) Class.forName(listClass).newInstance();168list.addAll(source);169trimmedSubList(list, new Callback() {170@Override171public void call(final List<Integer> list) {172if (list.size() < 1) {173return;174}175final List<Integer> target = new ArrayList<>(list.size());176final ListIterator<Integer> iterator = list.listIterator();177assertTrue(iterator.hasNext());178assertFalse(iterator.hasPrevious());179assertEquals(iterator.nextIndex(), 0);180assertEquals(iterator.previousIndex(), -1);181182iterator.forEachRemaining(target::add);183assertEquals(target, list);184185assertFalse(iterator.hasNext());186assertTrue(iterator.hasPrevious());187assertEquals(iterator.nextIndex(), list.size());188assertEquals(iterator.previousIndex(), list.size() - 1);189190try {191iterator.next();192fail(listClass + " iterator advanced beyond end");193} catch (NoSuchElementException ignore) {194}195}196});197}198}199200public void testOptimizedForEach() throws Exception {201final Integer[] data = new Integer[1000 * 1000];202for (int i=0; i < data.length; i++) {203data[i] = i;204}205final List<Integer> source = Arrays.asList(data);206207final String[] listClasses = {208"java.util.ArrayList",209"java.util.LinkedList",210"java.util.Vector",211"java.util.concurrent.CopyOnWriteArrayList"212};213214final int OFFSET = 3;215final List<Integer> target = new ArrayList<>(source);216for (final String listClass : listClasses) {217final List<Integer> list =218(List<Integer>) Class.forName(listClass).newInstance();219list.addAll(source);220final ListIterator<Integer> iterator = list.listIterator();221assertFalse(iterator.hasPrevious());222for (int i=0; i < OFFSET; i++) {223iterator.next();224}225assertTrue(iterator.hasNext());226assertTrue(iterator.hasPrevious());227assertEquals(iterator.nextIndex(), OFFSET);228assertEquals(iterator.previousIndex(), OFFSET - 1);229230iterator.forEachRemaining(e -> {231target.set(e, e + 1);232});233for (int i=OFFSET; i < data.length; i++) {234assertEquals(target.get(i).intValue(), source.get(i)+1);235}236237assertFalse(iterator.hasNext());238assertTrue(iterator.hasPrevious());239assertEquals(iterator.nextIndex(), data.length);240assertEquals(iterator.previousIndex(), data.length - 1);241242// CopyOnWriteArrayList.listIterator().remove() is unsupported243if (!"java.util.concurrent.CopyOnWriteArrayList".equals(listClass)) {244for (int i = data.length - 1; i >= 0; i--) {245iterator.remove(); // must not throw246if (i > 0) {247iterator.previous();248}249}250assertTrue(list.isEmpty());251}252253try {254iterator.next();255fail(listClass + " iterator advanced beyond end");256} catch (NoSuchElementException ignore) {257}258}259}260261@Test(enabled = false)262public void compareForEachPerformance() throws Exception {263final Integer[] data = new Integer[1000 * 100];264for (int i=0; i < data.length; i++) {265data[i] = i;266}267final List<Integer> source = Arrays.asList(data);268269final String[] iterableCollectionClasses = {270"java.util.ArrayList", // warmup, results discarded271"java.util.ArrayDeque",272"java.util.ArrayList",273"java.util.HashSet",274"java.util.LinkedHashSet",275"java.util.LinkedList",276"java.util.PriorityQueue",277"java.util.TreeSet",278"java.util.Vector",279"java.util.concurrent.ConcurrentLinkedDeque",280"java.util.concurrent.ConcurrentLinkedQueue",281"java.util.concurrent.ConcurrentSkipListSet",282"java.util.concurrent.CopyOnWriteArrayList",283"java.util.concurrent.CopyOnWriteArraySet",284"java.util.concurrent.LinkedBlockingDeque",285"java.util.concurrent.LinkedBlockingQueue",286"java.util.concurrent.LinkedTransferQueue",287"java.util.concurrent.PriorityBlockingQueue"288};289290boolean warmup = true;291final int ITERATIONS = 10;292final Integer[] target = new Integer[source.size()];293for (final String iterableClass : iterableCollectionClasses) {294final Class<? extends Collection<Integer>> type =295(Class<? extends Collection<Integer>>) Class.forName(iterableClass);296final Constructor<? extends Collection<Integer>> copyConstructor =297type.getConstructor(Collection.class);298final Iterable<Integer> iterable = copyConstructor.newInstance(source);299final Iterable<Integer> reference =300Collections.unmodifiableCollection((Collection<Integer>) iterable);301302for (int i=0; i < ITERATIONS; i++) {303final Iterator<Integer> iterator = reference.iterator();304final long forEachStart = System.nanoTime();305iterator.forEachRemaining(x -> {target[x.intValue()] = x;});306final long forEachEnd = System.nanoTime();307308final Iterator<Integer> iterator2 = reference.iterator();309Integer x;310final long iteratorStart = System.nanoTime();311while (iterator2.hasNext()) {312x = iterator2.next();313target[x.intValue()] = x;314}315final long iteratorEnd = System.nanoTime();316317if (warmup) { continue; } // warmup, discard results318final long forEachTime = forEachEnd - forEachStart;319final long iteratorTime = iteratorEnd - iteratorStart;320final long speedup = iteratorTime - forEachTime;321System.out.print(iterableClass);322System.out.print(" iterator: ");323System.out.print(iteratorTime);324System.out.print(", forEach: ");325System.out.print(forEachTime);326System.out.print(", speedup: ");327System.out.print(speedup);328System.out.print(" (");329System.out.print((speedup * 100) / iteratorTime);330System.out.print("%)\n");331}332if (warmup) { warmup = false; }333System.out.println();334}335}336337@Test(enabled = false)338public void compareSubListForEachPerformance() throws Exception {339final Integer[] data = new Integer[1000 * 100];340for (int i = 0; i < data.length; i++) {341data[i] = i;342}343final List<Integer> source = Arrays.asList(data);344345final String[] listClasses = {346"java.util.ArrayList", // warmup, results discarded347"java.util.ArrayList",348"java.util.LinkedList",349"java.util.Vector",350"java.util.concurrent.CopyOnWriteArrayList"351};352353boolean warmup = true;354final int ITERATIONS = 10;355final Integer[] target = new Integer[source.size()];356for (final String listClass : listClasses) {357final Class<? extends List<Integer >> type =358(Class<? extends List<Integer>>) Class.forName(listClass);359final Constructor<? extends List<Integer >> copyConstructor =360type.getConstructor(Collection.class);361final List<Integer> iterable = copyConstructor.newInstance(source);362final List<Integer> reference = Collections.unmodifiableList(iterable);363364for (int i = 0; i < ITERATIONS; i++) {365final Iterator<Integer> iterator = reference.subList(42, reference.size() - 37).iterator();366final long forEachStart = System.nanoTime();367iterator.forEachRemaining(x -> {368target[x.intValue()] = x;369});370final long forEachEnd = System.nanoTime();371372final Iterator<Integer> iterator2 = reference.iterator();373Integer x;374final long iteratorStart = System.nanoTime();375while (iterator2.hasNext()) {376x = iterator2.next();377target[x.intValue()] = x;378}379final long iteratorEnd = System.nanoTime();380381if (warmup) { continue; } // warmup, discard results382final long forEachTime = forEachEnd - forEachStart;383final long iteratorTime = iteratorEnd - iteratorStart;384final long speedup = iteratorTime - forEachTime;385System.out.print(listClass);386System.out.print(" iterator: ");387System.out.print(iteratorTime);388System.out.print(", forEach: ");389System.out.print(forEachTime);390System.out.print(", speedup: ");391System.out.print(speedup);392System.out.print(" (");393System.out.print((speedup * 100) / iteratorTime);394System.out.print("%)\n");395}396if (warmup) { warmup = false; }397System.out.println();398}399}400401static class IteratorWithRemove implements Iterator {402403public boolean removed;404405IteratorWithRemove() {406removed = false;407}408409@Override410public boolean hasNext() {411return false;412}413414@Override415public Object next() {416return null;417}418419@Override420public void remove() {421removed = true;422}423}424}425426427