8012645: Stream methods on BitSet, Random, ThreadLocalRandom, ZipFile
Reviewed-by: mduigou, henryjen, alanb, martin, psandoz
Contributed-by: akhil.arora@oracle.com, brian.goetz@oracle.com
--- a/jdk/src/share/classes/java/util/BitSet.java Wed May 01 15:08:31 2013 -0700
+++ b/jdk/src/share/classes/java/util/BitSet.java Thu May 02 09:18:56 2013 -0700
@@ -29,6 +29,8 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.LongBuffer;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
/**
* This class implements a vector of bits that grows as needed. Each
@@ -1188,4 +1190,47 @@
b.append('}');
return b.toString();
}
+
+ /**
+ * Returns a stream of indices for which this {@code BitSet}
+ * contains a bit in the set state. The indices are returned
+ * in order, from lowest to highest. The size of the stream
+ * is the number of bits in the set state, equal to the value
+ * returned by the {@link #cardinality()} method.
+ *
+ * <p>The bit set must remain constant during the execution of the
+ * terminal stream operation. Otherwise, the result of the terminal
+ * stream operation is undefined.
+ *
+ * @return a stream of integers representing set indices
+ * @since 1.8
+ */
+ public IntStream stream() {
+ class BitSetIterator implements PrimitiveIterator.OfInt {
+ int next = nextSetBit(0);
+
+ @Override
+ public boolean hasNext() {
+ return next != -1;
+ }
+
+ @Override
+ public int nextInt() {
+ if (next != -1) {
+ int ret = next;
+ next = nextSetBit(next+1);
+ return ret;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+ }
+
+ return StreamSupport.intStream(
+ () -> Spliterators.spliterator(
+ new BitSetIterator(), cardinality(),
+ Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED),
+ Spliterator.SIZED | Spliterator.SUBSIZED |
+ Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED);
+ }
}
--- a/jdk/src/share/classes/java/util/Random.java Wed May 01 15:08:31 2013 -0700
+++ b/jdk/src/share/classes/java/util/Random.java Thu May 02 09:18:56 2013 -0700
@@ -26,6 +26,10 @@
package java.util;
import java.io.*;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+
import sun.misc.Unsafe;
/**
@@ -513,6 +517,59 @@
}
/**
+ * Returns a stream of pseudorandom, uniformly distributed
+ * {@code integer} values from this random number generator's
+ * sequence. Values are obtained as needed by calling
+ * {@link #nextInt()}.
+ *
+ * @return an infinite stream of {@code integer} values
+ * @since 1.8
+ */
+ public IntStream ints() {
+ return IntStream.generate(this::nextInt);
+ }
+
+ /**
+ * Returns a stream of pseudorandom, uniformly distributed
+ * {@code long} values from this random number generator's
+ * sequence. Values are obtained as needed by calling
+ * {@link #nextLong()}.
+ *
+ * @return an infinite stream of {@code long} values
+ * @since 1.8
+ */
+ public LongStream longs() {
+ return LongStream.generate(this::nextLong);
+ }
+
+ /**
+ * Returns a stream of pseudorandom, uniformly distributed
+ * {@code double} values between {@code 0.0} and {@code 1.0}
+ * from this random number generator's sequence. Values are
+ * obtained as needed by calling {@link #nextDouble()}.
+ *
+ * @return an infinite stream of {@code double} values
+ * @since 1.8
+ */
+ public DoubleStream doubles() {
+ return DoubleStream.generate(this::nextDouble);
+ }
+
+ /**
+ * Returns a stream of pseudorandom, Gaussian ("normally")
+ * distributed {@code double} values with mean {@code 0.0}
+ * and standard deviation {@code 1.0} from this random number
+ * generator's sequence. Values are obtained as needed by
+ * calling {@link #nextGaussian()}.
+ *
+ * @return an infinite stream of {@code double} values
+ * @since 1.8
+ */
+ public DoubleStream gaussians() {
+ return DoubleStream.generate(this::nextGaussian);
+ }
+
+ /**
* Serializable fields for Random.
*
* @serialField seed long
--- a/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Wed May 01 15:08:31 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Thu May 02 09:18:56 2013 -0700
@@ -39,6 +39,9 @@
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
/**
* A random number generator isolated to the current thread. Like the
@@ -241,6 +244,26 @@
return offset + nextInt((int) n);
}
+ @Override
+ public IntStream ints() {
+ return IntStream.generate(() -> current().nextInt());
+ }
+
+ @Override
+ public LongStream longs() {
+ return LongStream.generate(() -> current().nextLong());
+ }
+
+ @Override
+ public DoubleStream doubles() {
+ return DoubleStream.generate(() -> current().nextDouble());
+ }
+
+ @Override
+ public DoubleStream gaussians() {
+ return DoubleStream.generate(() -> current().nextGaussian());
+ }
+
/**
* Returns a pseudorandom, uniformly distributed value between the
* given least value (inclusive) and bound (exclusive).
--- a/jdk/src/share/classes/java/util/jar/JarFile.java Wed May 01 15:08:31 2013 -0700
+++ b/jdk/src/share/classes/java/util/jar/JarFile.java Thu May 02 09:18:56 2013 -0700
@@ -29,6 +29,8 @@
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.*;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import java.util.zip.*;
import java.security.CodeSigner;
import java.security.cert.Certificate;
@@ -235,20 +237,42 @@
return null;
}
+ private class JarEntryIterator implements Enumeration<JarEntry>,
+ Iterator<JarEntry>
+ {
+ final Enumeration<? extends ZipEntry> e = JarFile.super.entries();
+
+ public boolean hasNext() {
+ return e.hasMoreElements();
+ }
+
+ public JarEntry next() {
+ ZipEntry ze = e.nextElement();
+ return new JarFileEntry(ze);
+ }
+
+ public boolean hasMoreElements() {
+ return hasNext();
+ }
+
+ public JarEntry nextElement() {
+ return next();
+ }
+ }
+
/**
* Returns an enumeration of the zip file entries.
*/
public Enumeration<JarEntry> entries() {
- final Enumeration<? extends ZipEntry> enum_ = super.entries();
- return new Enumeration<JarEntry>() {
- public boolean hasMoreElements() {
- return enum_.hasMoreElements();
- }
- public JarFileEntry nextElement() {
- ZipEntry ze = enum_.nextElement();
- return new JarFileEntry(ze);
- }
- };
+ return new JarEntryIterator();
+ }
+
+ @Override
+ public Stream<JarEntry> stream() {
+ return StreamSupport.stream(Spliterators.spliterator(
+ new JarEntryIterator(), size(),
+ Spliterator.ORDERED | Spliterator.DISTINCT |
+ Spliterator.IMMUTABLE | Spliterator.NONNULL));
}
private class JarFileEntry extends JarEntry {
--- a/jdk/src/share/classes/java/util/zip/ZipFile.java Wed May 01 15:08:31 2013 -0700
+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java Thu May 02 09:18:56 2013 -0700
@@ -36,11 +36,15 @@
import java.util.Deque;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.Spliterators;
import java.util.WeakHashMap;
-import java.security.AccessController;
-import sun.security.action.GetPropertyAction;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
import static java.util.zip.ZipConstants64.*;
/**
@@ -471,49 +475,80 @@
return name;
}
+ private class ZipEntryIterator implements Enumeration<ZipEntry>, Iterator<ZipEntry> {
+ private int i = 0;
+
+ public ZipEntryIterator() {
+ ensureOpen();
+ }
+
+ public boolean hasMoreElements() {
+ return hasNext();
+ }
+
+ public boolean hasNext() {
+ synchronized (ZipFile.this) {
+ ensureOpen();
+ return i < total;
+ }
+ }
+
+ public ZipEntry nextElement() {
+ return next();
+ }
+
+ public ZipEntry next() {
+ synchronized (ZipFile.this) {
+ ensureOpen();
+ if (i >= total) {
+ throw new NoSuchElementException();
+ }
+ long jzentry = getNextEntry(jzfile, i++);
+ if (jzentry == 0) {
+ String message;
+ if (closeRequested) {
+ message = "ZipFile concurrently closed";
+ } else {
+ message = getZipMessage(ZipFile.this.jzfile);
+ }
+ throw new ZipError("jzentry == 0" +
+ ",\n jzfile = " + ZipFile.this.jzfile +
+ ",\n total = " + ZipFile.this.total +
+ ",\n name = " + ZipFile.this.name +
+ ",\n i = " + i +
+ ",\n message = " + message
+ );
+ }
+ ZipEntry ze = getZipEntry(null, jzentry);
+ freeEntry(jzfile, jzentry);
+ return ze;
+ }
+ }
+ }
+
/**
* Returns an enumeration of the ZIP file entries.
* @return an enumeration of the ZIP file entries
* @throws IllegalStateException if the zip file has been closed
*/
public Enumeration<? extends ZipEntry> entries() {
- ensureOpen();
- return new Enumeration<ZipEntry>() {
- private int i = 0;
- public boolean hasMoreElements() {
- synchronized (ZipFile.this) {
- ensureOpen();
- return i < total;
- }
- }
- public ZipEntry nextElement() throws NoSuchElementException {
- synchronized (ZipFile.this) {
- ensureOpen();
- if (i >= total) {
- throw new NoSuchElementException();
- }
- long jzentry = getNextEntry(jzfile, i++);
- if (jzentry == 0) {
- String message;
- if (closeRequested) {
- message = "ZipFile concurrently closed";
- } else {
- message = getZipMessage(ZipFile.this.jzfile);
- }
- throw new ZipError("jzentry == 0" +
- ",\n jzfile = " + ZipFile.this.jzfile +
- ",\n total = " + ZipFile.this.total +
- ",\n name = " + ZipFile.this.name +
- ",\n i = " + i +
- ",\n message = " + message
- );
- }
- ZipEntry ze = getZipEntry(null, jzentry);
- freeEntry(jzfile, jzentry);
- return ze;
- }
- }
- };
+ return new ZipEntryIterator();
+ }
+
+ /**
+ * Return an ordered {@code Stream} over the ZIP file entries.
+ * Entries appear in the {@code Stream} in the order they appear in
+ * the central directory of the ZIP file.
+ *
+ * @return an ordered {@code Stream} of entries in this ZIP file
+ * @throws IllegalStateException if the zip file has been closed
+ * @since 1.8
+ */
+ public Stream<? extends ZipEntry> stream() {
+ return StreamSupport.stream(Spliterators.spliterator(
+ new ZipEntryIterator(), size(),
+ Spliterator.ORDERED | Spliterator.DISTINCT |
+ Spliterator.IMMUTABLE | Spliterator.NONNULL));
}
private ZipEntry getZipEntry(String name, long jzentry) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/BitSet/BitSetStreamTest.java Thu May 02 09:18:56 2013 -0700
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, 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
+ * 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.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.Integer;
+import java.lang.Object;
+import java.lang.System;
+import java.util.BitSet;
+import java.util.OptionalInt;
+import java.util.PrimitiveIterator;
+import java.util.Random;
+import java.util.function.IntSupplier;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/**
+ * @test
+ * @summary test BitSet stream
+ * @bug 8012645
+ * @run testng BitSetStreamTest
+ */
+public class BitSetStreamTest {
+ static class Fibs implements IntSupplier {
+ private int n1 = 0;
+ private int n2 = 1;
+
+ static int fibs(int n) {
+ Fibs f = new Fibs();
+ while (n-- > 0) f.getAsInt();
+ return f.getAsInt();
+ }
+
+ public int getAsInt() { int s = n1; n1 = n2; n2 = s + n1; return s; }
+ }
+
+ private static final Object[][] testcases = new Object[][] {
+ { "none", IntStream.empty() },
+ { "index 0", IntStream.of(0) },
+ { "index 255", IntStream.of(255) },
+ { "every bit", IntStream.range(0, 255) },
+ { "step 2", IntStream.range(0, 255, 2) },
+ { "step 3", IntStream.range(0, 255, 3) },
+ { "step 5", IntStream.range(0, 255, 5) },
+ { "step 7", IntStream.range(0, 255, 7) },
+ { "1, 10, 100, 1000", IntStream.of(1, 10, 100, 1000) },
+ { "25 fibs", IntStream.generate(new Fibs()).limit(25) }
+ };
+
+ @DataProvider(name = "cases")
+ public static Object[][] produceCases() {
+ return testcases;
+ }
+
+ @Test
+ public void testFibs() {
+ Fibs f = new Fibs();
+ assertEquals(0, f.getAsInt());
+ assertEquals(1, f.getAsInt());
+ assertEquals(1, f.getAsInt());
+ assertEquals(2, f.getAsInt());
+ assertEquals(3, f.getAsInt());
+ assertEquals(5, f.getAsInt());
+ assertEquals(8, f.getAsInt());
+ assertEquals(13, f.getAsInt());
+ assertEquals(987, Fibs.fibs(16));
+ }
+
+ @Test(dataProvider = "cases")
+ public void testBitsetStream(String name, IntStream data) {
+ BitSet bs = new BitSet();
+ long setBits = data.distinct()
+ .peek(i -> bs.set(i))
+ .count();
+
+ assertEquals(bs.cardinality(), setBits);
+ assertEquals(bs.cardinality(), bs.stream().reduce(0, (s, i) -> s+1));
+
+ PrimitiveIterator.OfInt it = bs.stream().iterator();
+ for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
+ assertTrue(it.hasNext());
+ assertEquals(it.nextInt(), i);
+ }
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void testRandomStream() {
+ final int size = 1024 * 1024;
+ final int[] seeds = {
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
+ 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
+ final byte[] bytes = new byte[size];
+ for (int seed : seeds) {
+ final Random random = new Random(seed);
+ random.nextBytes(bytes);
+ final BitSet bitSet = BitSet.valueOf(bytes);
+ final int cardinality = bitSet.cardinality();
+ final IntStream stream = bitSet.stream();
+ final int[] array = stream.toArray();
+ assertEquals(array.length, cardinality);
+ int nextSetBit = -1;
+ for (int i=0; i < cardinality; i++) {
+ nextSetBit = bitSet.nextSetBit(nextSetBit + 1);
+ assertEquals(array[i], nextSetBit);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Random/RandomStreamTest.java Thu May 02 09:18:56 2013 -0700
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2012, 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
+ * 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.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Random;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.DoubleStream;
+import java.util.stream.Stream;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @test
+ * @run testng RandomStreamTest
+ * @summary test stream methods on Random
+ * @author Brian Goetz
+ */
+public class RandomStreamTest {
+
+ private static final int SIZE = 1000;
+
+ @DataProvider(name = "suppliers")
+ public Object[][] randomSuppliers() {
+ return new Object[][] {
+ {new Random(), SIZE},
+ {new SecureRandom(), SIZE}
+ };
+ }
+
+ @Test(dataProvider = "suppliers")
+ public void testRandomIntStream(final Random random, final int count) {
+ final List<Integer> destination = new ArrayList<>(count);
+ random.ints().limit(count).forEach(destination::add);
+ assertEquals(destination.size(), count);
+ }
+
+ @Test(dataProvider = "suppliers")
+ public void testRandomLongStream(final Random random, final int count) {
+ final List<Long> destination = new ArrayList<>(count);
+ random.longs().limit(count).forEach(destination::add);
+ assertEquals(destination.size(), count);
+ }
+
+ @Test(dataProvider = "suppliers")
+ public void testRandomDoubleStream(final Random random, final int count) {
+ final List<Double> destination = new ArrayList<>(count);
+ random.doubles().limit(count).forEach(destination::add);
+ random.doubles().limit(count).forEach(d -> assertTrue(d >= 0.0 && d < 1.0));
+ assertEquals(destination.size(), count);
+ }
+
+ @Test(dataProvider = "suppliers")
+ public void testRandomGaussianStream(final Random random, final int count) {
+ final List<Double> destination = new ArrayList<>(count);
+ random.gaussians().limit(count).forEach(destination::add);
+ assertEquals(destination.size(), count);
+ }
+
+ @Test
+ public void testIntStream() {
+ final long seed = System.currentTimeMillis();
+ final Random r1 = new Random(seed);
+ final int[] a = new int[SIZE];
+ for (int i=0; i < SIZE; i++) {
+ a[i] = r1.nextInt();
+ }
+
+ final Random r2 = new Random(seed); // same seed
+ final int[] b = r2.ints().limit(SIZE).toArray();
+ assertEquals(a, b);
+ }
+
+ @Test
+ public void testLongStream() {
+ final long seed = System.currentTimeMillis();
+ final Random r1 = new Random(seed);
+ final long[] a = new long[SIZE];
+ for (int i=0; i < SIZE; i++) {
+ a[i] = r1.nextLong();
+ }
+
+ final Random r2 = new Random(seed); // same seed
+ final long[] b = r2.longs().limit(SIZE).toArray();
+ assertEquals(a, b);
+ }
+
+ @Test
+ public void testDoubleStream() {
+ final long seed = System.currentTimeMillis();
+ final Random r1 = new Random(seed);
+ final double[] a = new double[SIZE];
+ for (int i=0; i < SIZE; i++) {
+ a[i] = r1.nextDouble();
+ }
+
+ final Random r2 = new Random(seed); // same seed
+ final double[] b = r2.doubles().limit(SIZE).toArray();
+ assertEquals(a, b);
+ }
+
+ @Test
+ public void testGaussianStream() {
+ final long seed = System.currentTimeMillis();
+ final Random r1 = new Random(seed);
+ final double[] a = new double[SIZE];
+ for (int i=0; i < SIZE; i++) {
+ a[i] = r1.nextGaussian();
+ }
+
+ final Random r2 = new Random(seed); // same seed
+ final double[] b = r2.gaussians().limit(SIZE).toArray();
+ assertEquals(a, b);
+ }
+
+ @Test
+ public void testThreadLocalIntStream() throws InterruptedException {
+ final ExecutorService e = Executors.newFixedThreadPool(10);
+ final ThreadLocalRandom tlr = ThreadLocalRandom.current();
+
+ final class RandomTask implements Runnable {
+ int[] randoms;
+
+ @Override
+ public void run() {
+ randoms = tlr.ints().limit(SIZE).toArray();
+ }
+ }
+ final RandomTask[] tasks = new RandomTask[10];
+ for (int i=0; i < tasks.length; i++) {
+ tasks[i] = new RandomTask();
+ }
+ for (int i=0; i < tasks.length; i++) {
+ e.submit(tasks[i]);
+ }
+ e.shutdown();
+ e.awaitTermination(3, TimeUnit.SECONDS);
+ for (int i=1; i < tasks.length; i++) {
+ assertFalse(Arrays.equals(tasks[0].randoms, tasks[i].randoms));
+ }
+ }
+
+ @Test
+ public void testThreadLocalLongStream() throws InterruptedException {
+ final ExecutorService e = Executors.newFixedThreadPool(10);
+ final ThreadLocalRandom tlr = ThreadLocalRandom.current();
+
+ final class RandomTask implements Runnable {
+ long[] randoms;
+
+ @Override
+ public void run() {
+ randoms = tlr.longs().limit(SIZE).toArray();
+ }
+ }
+ final RandomTask[] tasks = new RandomTask[10];
+ for (int i=0; i < tasks.length; i++) {
+ tasks[i] = new RandomTask();
+ }
+ for (int i=0; i < tasks.length; i++) {
+ e.submit(tasks[i]);
+ }
+ e.shutdown();
+ e.awaitTermination(3, TimeUnit.SECONDS);
+ for (int i=1; i < tasks.length; i++) {
+ assertFalse(Arrays.equals(tasks[0].randoms, tasks[i].randoms));
+ }
+ }
+
+ @Test
+ public void testThreadLocalDoubleStream() throws InterruptedException {
+ final ExecutorService e = Executors.newFixedThreadPool(10);
+ final ThreadLocalRandom tlr = ThreadLocalRandom.current();
+
+ final class RandomTask implements Runnable {
+ double[] randoms;
+
+ @Override
+ public void run() {
+ randoms = tlr.doubles().limit(SIZE).toArray();
+ }
+ }
+ final RandomTask[] tasks = new RandomTask[10];
+ for (int i=0; i < tasks.length; i++) {
+ tasks[i] = new RandomTask();
+ }
+ for (int i=0; i < tasks.length; i++) {
+ e.submit(tasks[i]);
+ }
+ e.shutdown();
+ e.awaitTermination(3, TimeUnit.SECONDS);
+ for (int i=1; i < tasks.length; i++) {
+ assertFalse(Arrays.equals(tasks[0].randoms, tasks[i].randoms));
+ }
+ }
+
+ @Test
+ public void testThreadLocalGaussianStream() throws InterruptedException {
+ final ExecutorService e = Executors.newFixedThreadPool(10);
+ final ThreadLocalRandom tlr = ThreadLocalRandom.current();
+
+ final class RandomTask implements Runnable {
+ double[] randoms;
+
+ @Override
+ public void run() {
+ randoms = tlr.gaussians().limit(SIZE).toArray();
+ }
+ }
+ final RandomTask[] tasks = new RandomTask[10];
+ for (int i=0; i < tasks.length; i++) {
+ tasks[i] = new RandomTask();
+ }
+ for (int i=0; i < tasks.length; i++) {
+ e.submit(tasks[i]);
+ }
+ e.shutdown();
+ e.awaitTermination(3, TimeUnit.SECONDS);
+ for (int i=1; i < tasks.length; i++) {
+ assertFalse(Arrays.equals(tasks[0].randoms, tasks[i].randoms));
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/ZipFile/StreamZipEntriesTest.java Thu May 02 09:18:56 2013 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2012, 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
+ * 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
+ * @run testng StreamZipEntriesTest
+ * @summary Make sure we can stream entries of a zip file.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.Object;
+import java.lang.System;
+import java.util.jar.JarFile;
+import java.util.jar.JarEntry;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+public class StreamZipEntriesTest {
+
+ @Test
+ public void testStreamZip() throws IOException {
+ try (ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), "input.zip"))) {
+ zf.stream().forEach(e -> assertTrue(e instanceof ZipEntry));
+ zf.stream().forEach(e -> assertEquals(e.toString(), "ReadZip.java"));
+
+ Object elements[] = zf.stream().toArray();
+ assertEquals(1, elements.length);
+ assertEquals(elements[0].toString(), "ReadZip.java");
+ }
+ }
+
+ @Test
+ public void testStreamJar() throws IOException {
+ try (JarFile jf = new JarFile(new File(System.getProperty("test.src", "."), "input.jar"))) {
+ jf.stream().forEach(e -> assertTrue(e instanceof JarEntry));
+
+ Object elements[] = jf.stream().toArray();
+ assertEquals(3, elements.length);
+ assertEquals(elements[0].toString(), "META-INF/");
+ assertEquals(elements[1].toString(), "META-INF/MANIFEST.MF");
+ assertEquals(elements[2].toString(), "ReleaseInflater.java");
+ }
+ }
+
+ @Test
+ public void testClosedZipFile() throws IOException {
+ ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), "input.zip"));
+ zf.close();
+ try {
+ Stream s = zf.stream();
+ fail("Should have thrown IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected;
+ }
+ }
+
+ @Test
+ public void testClosedJarFile() throws IOException {
+ JarFile jf = new JarFile(new File(System.getProperty("test.src", "."), "input.jar"));
+ jf.close();
+ try {
+ Stream s = jf.stream();
+ fail("Should have thrown IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected;
+ }
+ }
+}