提交 2e7d5571 编写于 作者: M mduigou

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
上级 4dee8d56
......@@ -29,6 +29,8 @@ import java.io.*;
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 @@ public class BitSet implements Cloneable, java.io.Serializable {
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);
}
}
......@@ -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;
/**
......@@ -512,6 +516,59 @@ class Random implements java.io.Serializable {
}
}
/**
* 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.
*
......
......@@ -39,6 +39,9 @@ import java.io.ObjectStreamField;
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 @@ public class ThreadLocalRandom extends Random {
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).
......
......@@ -29,6 +29,8 @@ import java.io.*;
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 @@ class JarFile extends ZipFile {
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();
return new JarEntryIterator();
}
public JarFileEntry nextElement() {
ZipEntry ze = enum_.nextElement();
return new JarFileEntry(ze);
}
};
@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 {
......
......@@ -36,11 +36,15 @@ import java.util.ArrayDeque;
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,22 +475,29 @@ class ZipFile implements ZipConstants, Closeable {
return name;
}
/**
* 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 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() throws NoSuchElementException {
public ZipEntry nextElement() {
return next();
}
public ZipEntry next() {
synchronized (ZipFile.this) {
ensureOpen();
if (i >= total) {
......@@ -513,7 +524,31 @@ class ZipFile implements ZipConstants, Closeable {
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() {
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) {
......
/*
* 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);
}
}
}
}
/*
* 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));
}
}
}
/*
* 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;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册