mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-20 15:25:27 +00:00
Merge
This commit is contained in:
commit
eeb2dcdfe2
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
@ -203,6 +203,12 @@ class Inet6Address extends InetAddress {
|
||||
*/
|
||||
private transient NetworkInterface scope_ifname; // null
|
||||
|
||||
/**
|
||||
* set if the object is constructed with a scoped
|
||||
* interface instead of a numeric scope id.
|
||||
*/
|
||||
private boolean scope_ifname_set; // false;
|
||||
|
||||
private static final long serialVersionUID = 6880410070516793377L;
|
||||
|
||||
// Perform native initialization
|
||||
@ -332,7 +338,7 @@ class Inet6Address extends InetAddress {
|
||||
}
|
||||
}
|
||||
|
||||
private void initif(String hostName, byte addr[],NetworkInterface nif)
|
||||
private void initif(String hostName, byte addr[], NetworkInterface nif)
|
||||
throws UnknownHostException
|
||||
{
|
||||
holder().hostName = hostName;
|
||||
@ -344,6 +350,7 @@ class Inet6Address extends InetAddress {
|
||||
scope_ifname = nif;
|
||||
scope_id = deriveNumericScope(nif);
|
||||
scope_id_set = true;
|
||||
scope_ifname_set = true; // for consistency
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,6 +438,7 @@ class Inet6Address extends InetAddress {
|
||||
try {
|
||||
scope_ifname = NetworkInterface.getByName(ifname);
|
||||
if (scope_ifname != null) {
|
||||
scope_ifname_set = true;
|
||||
try {
|
||||
scope_id = deriveNumericScope(scope_ifname);
|
||||
} catch (UnknownHostException e) {
|
||||
@ -438,6 +446,12 @@ class Inet6Address extends InetAddress {
|
||||
// the machine being used for deserialization has
|
||||
// the same interface name but without IPv6 configured.
|
||||
}
|
||||
} else {
|
||||
/* the interface does not exist on this system, so we clear
|
||||
* the scope information completely */
|
||||
scope_id_set = false;
|
||||
scope_ifname_set = false;
|
||||
scope_id = 0;
|
||||
}
|
||||
} catch (SocketException e) {}
|
||||
|
||||
@ -784,8 +798,10 @@ class Inet6Address extends InetAddress {
|
||||
private synchronized void writeObject(java.io.ObjectOutputStream s)
|
||||
throws IOException
|
||||
{
|
||||
if (scope_ifname != null)
|
||||
if (scope_ifname != null) {
|
||||
ifname = scope_ifname.getName();
|
||||
scope_ifname_set = true;
|
||||
}
|
||||
s.defaultWriteObject();
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,13 +44,16 @@ import java.util.logging.Logger;
|
||||
*
|
||||
* <P>When a Driver class is loaded, it should create an instance of
|
||||
* itself and register it with the DriverManager. This means that a
|
||||
* user can load and register a driver by calling
|
||||
* <pre>
|
||||
* <code>Class.forName("foo.bah.Driver")</code>
|
||||
* </pre>
|
||||
*
|
||||
* user can load and register a driver by calling:
|
||||
* <p>
|
||||
* {@code Class.forName("foo.bah.Driver")}
|
||||
* <p>
|
||||
* A JDBC driver may create a {@linkplain DriverAction} implementation in order
|
||||
* to receive notifications when {@linkplain DriverManager#deregisterDriver} has
|
||||
* been called.
|
||||
* @see DriverManager
|
||||
* @see Connection
|
||||
* @see DriverAction
|
||||
*/
|
||||
public interface Driver {
|
||||
|
||||
|
||||
66
jdk/src/share/classes/java/sql/DriverAction.java
Normal file
66
jdk/src/share/classes/java/sql/DriverAction.java
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.sql;
|
||||
|
||||
/**
|
||||
* An interface that must be implemented when a {@linkplain Driver} wants to be
|
||||
* notified by {@code DriverManager}.
|
||||
*<P>
|
||||
* A {@code DriverAction} implementation is not intended to be used
|
||||
* directly by applications. A JDBC Driver may choose
|
||||
* to create its {@code DriverAction} implementation in a private class
|
||||
* to avoid it being called directly.
|
||||
* <o>
|
||||
* The JDBC driver's static initialization block must call
|
||||
* {@linkplain DriverManager#registerDriver(java.sql.Driver, java.sql.DriverAction) } in order
|
||||
* to inform {@code DriverManager} which {@code DriverAction} implementation to
|
||||
* call when the JDBC driver is de-registered.
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface DriverAction {
|
||||
/**
|
||||
* Method called by
|
||||
* {@linkplain DriverManager#deregisterDriver(Driver) }
|
||||
* to notify the JDBC driver that it was de-registered.
|
||||
* <p>
|
||||
* The {@code deregister} method is intended only to be used by JDBC Drivers
|
||||
* and not by applications. JDBC drivers are recommended to not implement
|
||||
* {@code DriverAction} in a public class. If there are active
|
||||
* connections to the database at the time that the {@code deregister}
|
||||
* method is called, it is implementation specific as to whether the
|
||||
* connections are closed or allowed to continue. Once this method is
|
||||
* called, it is implementation specific as to whether the driver may
|
||||
* limit the ability to create new connections to the database, invoke
|
||||
* other {@code Driver} methods or throw a {@code SQLException}.
|
||||
* Consult your JDBC driver's documentation for additional information
|
||||
* on its behavior.
|
||||
* @see DriverManager#registerDriver(java.sql.Driver, java.sql.DriverAction)
|
||||
* @see DriverManager#deregisterDriver(Driver)
|
||||
* @since 1.8
|
||||
*/
|
||||
void deregister();
|
||||
|
||||
}
|
||||
@ -110,6 +110,14 @@ public class DriverManager {
|
||||
final static SQLPermission SET_LOG_PERMISSION =
|
||||
new SQLPermission("setLog");
|
||||
|
||||
/**
|
||||
* The {@code SQLPermission} constant that allows the
|
||||
* un-register a registered JDBC driver.
|
||||
* @since 1.8
|
||||
*/
|
||||
final static SQLPermission DEREGISTER_DRIVER_PERMISSION =
|
||||
new SQLPermission("deregisterDriver");
|
||||
|
||||
//--------------------------JDBC 2.0-----------------------------
|
||||
|
||||
/**
|
||||
@ -309,21 +317,42 @@ public class DriverManager {
|
||||
|
||||
|
||||
/**
|
||||
* Registers the given driver with the <code>DriverManager</code>.
|
||||
* Registers the given driver with the {@code DriverManager}.
|
||||
* A newly-loaded driver class should call
|
||||
* the method <code>registerDriver</code> to make itself
|
||||
* known to the <code>DriverManager</code>.
|
||||
* the method {@code registerDriver} to make itself
|
||||
* known to the {@code DriverManager}. If the driver had previously been
|
||||
* registered, no action is taken.
|
||||
*
|
||||
* @param driver the new JDBC Driver that is to be registered with the
|
||||
* <code>DriverManager</code>
|
||||
* {@code DriverManager}
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public static synchronized void registerDriver(java.sql.Driver driver)
|
||||
throws SQLException {
|
||||
|
||||
registerDriver(driver, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given driver with the {@code DriverManager}.
|
||||
* A newly-loaded driver class should call
|
||||
* the method {@code registerDriver} to make itself
|
||||
* known to the {@code DriverManager}. If the driver had previously been
|
||||
* registered, no action is taken.
|
||||
*
|
||||
* @param driver the new JDBC Driver that is to be registered with the
|
||||
* {@code DriverManager}
|
||||
* @param da the {@code DriverAction} implementation to be used when
|
||||
* {@code DriverManager#deregisterDriver} is called
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public static synchronized void registerDriver(java.sql.Driver driver,
|
||||
DriverAction da)
|
||||
throws SQLException {
|
||||
|
||||
/* Register the driver if it has not already been added to our list */
|
||||
if(driver != null) {
|
||||
registeredDrivers.addIfAbsent(new DriverInfo(driver));
|
||||
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
|
||||
} else {
|
||||
// This is for compatibility with the original DriverManager
|
||||
throw new NullPointerException();
|
||||
@ -334,11 +363,29 @@ public class DriverManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops a driver from the <code>DriverManager</code>'s list.
|
||||
* Applets can only deregister drivers from their own classloaders.
|
||||
* Removes the specified driver from the {@code DriverManager}'s list of
|
||||
* registered drivers.
|
||||
* <p>
|
||||
* If a {@code null} value is specified for the driver to be removed, then no
|
||||
* action is taken.
|
||||
* <p>
|
||||
* If a security manager exists and its {@code checkPermission} denies
|
||||
* permission, then a {@code SecurityException} will be thrown.
|
||||
* <p>
|
||||
* If the specified driver is not found in the list of registered drivers,
|
||||
* then no action is taken. If the driver was found, it will be removed
|
||||
* from the list of registered drivers.
|
||||
* <p>
|
||||
* If a {@code DriverAction} instance was specified when the JDBC driver was
|
||||
* registered, its deregister method will be called
|
||||
* prior to the driver being removed from the list of registered drivers.
|
||||
*
|
||||
* @param driver the JDBC Driver to drop
|
||||
* @param driver the JDBC Driver to remove
|
||||
* @exception SQLException if a database access error occurs
|
||||
* @throws SecurityException if a security manager exists and its
|
||||
* {@code checkPermission} method denies permission to deregister a driver.
|
||||
*
|
||||
* @see SecurityManager#checkPermission
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static synchronized void deregisterDriver(Driver driver)
|
||||
@ -347,11 +394,22 @@ public class DriverManager {
|
||||
return;
|
||||
}
|
||||
|
||||
SecurityManager sec = System.getSecurityManager();
|
||||
if (sec != null) {
|
||||
sec.checkPermission(DEREGISTER_DRIVER_PERMISSION);
|
||||
}
|
||||
|
||||
println("DriverManager.deregisterDriver: " + driver);
|
||||
|
||||
DriverInfo aDriver = new DriverInfo(driver);
|
||||
DriverInfo aDriver = new DriverInfo(driver, null);
|
||||
if(registeredDrivers.contains(aDriver)) {
|
||||
if (isDriverAllowed(driver, Reflection.getCallerClass())) {
|
||||
DriverInfo di = registeredDrivers.get(registeredDrivers.indexOf(aDriver));
|
||||
// If a DriverAction was specified, Call it to notify the
|
||||
// driver that it has been deregistered
|
||||
if(di.action() != null) {
|
||||
di.action().deregister();
|
||||
}
|
||||
registeredDrivers.remove(aDriver);
|
||||
} else {
|
||||
// If the caller does not have permission to load the driver then
|
||||
@ -639,8 +697,10 @@ public class DriverManager {
|
||||
class DriverInfo {
|
||||
|
||||
final Driver driver;
|
||||
DriverInfo(Driver driver) {
|
||||
DriverAction da;
|
||||
DriverInfo(Driver driver, DriverAction action) {
|
||||
this.driver = driver;
|
||||
da = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -658,4 +718,8 @@ class DriverInfo {
|
||||
public String toString() {
|
||||
return ("driver[className=" + driver + "]");
|
||||
}
|
||||
|
||||
DriverAction action() {
|
||||
return da;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -30,8 +30,9 @@ import java.security.*;
|
||||
|
||||
/**
|
||||
* The permission for which the <code>SecurityManager</code> will check
|
||||
* when code that is running in an applet, or an application with a
|
||||
* when code that is running an application with a
|
||||
* <code>SecurityManager</code> enabled, calls the
|
||||
* {@code DriverManager.deregisterDriver} method,
|
||||
* <code>DriverManager.setLogWriter</code> method,
|
||||
* <code>DriverManager.setLogStream</code> (deprecated) method,
|
||||
* {@code SyncFactory.setJNDIContext} method,
|
||||
@ -95,14 +96,16 @@ import java.security.*;
|
||||
* <code>Connection</code> or
|
||||
* objects created from the <code>Connection</code>
|
||||
* will wait for the database to reply to any one request.</td>
|
||||
* <tr>
|
||||
* <td>deregisterDriver</td>
|
||||
* <td>Allows the invocation of the {@code DriverManager}
|
||||
* method {@code deregisterDriver}</td>
|
||||
* <td>Permits an application to remove a JDBC driver from the list of
|
||||
* registered Drivers and release its resources.</td>
|
||||
* </tr>
|
||||
* </tr>
|
||||
* </table>
|
||||
*<p>
|
||||
* The person running an applet decides what permissions to allow
|
||||
* and will run the <code>Policy Tool</code> to create an
|
||||
* <code>SQLPermission</code> in a policy file. A programmer does
|
||||
* not use a constructor directly to create an instance of <code>SQLPermission</code>
|
||||
* but rather uses a tool.
|
||||
* @since 1.3
|
||||
* @see java.security.BasicPermission
|
||||
* @see java.security.Permission
|
||||
|
||||
@ -25,7 +25,21 @@
|
||||
|
||||
package java.util;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.DoubleBinaryOperator;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.function.IntToDoubleFunction;
|
||||
import java.util.function.IntToLongFunction;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import java.util.stream.DoubleStream;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.LongStream;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
import static java.util.ArraysParallelSortHelpers.*;
|
||||
|
||||
/**
|
||||
@ -4306,17 +4320,171 @@ public class Arrays {
|
||||
dejaVu.remove(a);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a {@link Spliterator} covering all of the specified array.
|
||||
* Set all elements of the specified array, using the provided
|
||||
* generator function to compute each element.
|
||||
*
|
||||
* <p>If the generator function throws an exception, it is relayed to
|
||||
* the caller and the array is left in an indeterminate state.
|
||||
*
|
||||
* @param <T> type of elements of the array
|
||||
* @param array array to be initialized
|
||||
* @param generator a function accepting an index and producing the desired
|
||||
* value for that position
|
||||
* @throws NullPointerException if the generator is null
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <T> void setAll(T[] array, IntFunction<? extends T> generator) {
|
||||
Objects.requireNonNull(generator);
|
||||
for (int i = 0; i < array.length; i++)
|
||||
array[i] = generator.apply(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all elements of the specified array, in parallel, using the
|
||||
* provided generator function to compute each element.
|
||||
*
|
||||
* <p>If the generator function throws an exception, an unchecked exception
|
||||
* is thrown from {@code parallelSetAll} and the array is left in an
|
||||
* indeterminate state.
|
||||
*
|
||||
* @param <T> type of elements of the array
|
||||
* @param array array to be initialized
|
||||
* @param generator a function accepting an index and producing the desired
|
||||
* value for that position
|
||||
* @throws NullPointerException if the generator is null
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <T> void parallelSetAll(T[] array, IntFunction<? extends T> generator) {
|
||||
Objects.requireNonNull(generator);
|
||||
IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.apply(i); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all elements of the specified array, using the provided
|
||||
* generator function to compute each element.
|
||||
*
|
||||
* <p>If the generator function throws an exception, it is relayed to
|
||||
* the caller and the array is left in an indeterminate state.
|
||||
*
|
||||
* @param array array to be initialized
|
||||
* @param generator a function accepting an index and producing the desired
|
||||
* value for that position
|
||||
* @throws NullPointerException if the generator is null
|
||||
* @since 1.8
|
||||
*/
|
||||
public static void setAll(int[] array, IntUnaryOperator generator) {
|
||||
Objects.requireNonNull(generator);
|
||||
for (int i = 0; i < array.length; i++)
|
||||
array[i] = generator.applyAsInt(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all elements of the specified array, in parallel, using the
|
||||
* provided generator function to compute each element.
|
||||
*
|
||||
* <p>If the generator function throws an exception, an unchecked exception
|
||||
* is thrown from {@code parallelSetAll} and the array is left in an
|
||||
* indeterminate state.
|
||||
*
|
||||
* @param array array to be initialized
|
||||
* @param generator a function accepting an index and producing the desired
|
||||
* value for that position
|
||||
* @throws NullPointerException if the generator is null
|
||||
* @since 1.8
|
||||
*/
|
||||
public static void parallelSetAll(int[] array, IntUnaryOperator generator) {
|
||||
Objects.requireNonNull(generator);
|
||||
IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsInt(i); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all elements of the specified array, using the provided
|
||||
* generator function to compute each element.
|
||||
*
|
||||
* <p>If the generator function throws an exception, it is relayed to
|
||||
* the caller and the array is left in an indeterminate state.
|
||||
*
|
||||
* @param array array to be initialized
|
||||
* @param generator a function accepting an index and producing the desired
|
||||
* value for that position
|
||||
* @throws NullPointerException if the generator is null
|
||||
* @since 1.8
|
||||
*/
|
||||
public static void setAll(long[] array, IntToLongFunction generator) {
|
||||
Objects.requireNonNull(generator);
|
||||
for (int i = 0; i < array.length; i++)
|
||||
array[i] = generator.applyAsLong(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all elements of the specified array, in parallel, using the
|
||||
* provided generator function to compute each element.
|
||||
*
|
||||
* <p>If the generator function throws an exception, an unchecked exception
|
||||
* is thrown from {@code parallelSetAll} and the array is left in an
|
||||
* indeterminate state.
|
||||
*
|
||||
* @param array array to be initialized
|
||||
* @param generator a function accepting an index and producing the desired
|
||||
* value for that position
|
||||
* @throws NullPointerException if the generator is null
|
||||
* @since 1.8
|
||||
*/
|
||||
public static void parallelSetAll(long[] array, IntToLongFunction generator) {
|
||||
Objects.requireNonNull(generator);
|
||||
IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsLong(i); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all elements of the specified array, using the provided
|
||||
* generator function to compute each element.
|
||||
*
|
||||
* <p>If the generator function throws an exception, it is relayed to
|
||||
* the caller and the array is left in an indeterminate state.
|
||||
*
|
||||
* @param array array to be initialized
|
||||
* @param generator a function accepting an index and producing the desired
|
||||
* value for that position
|
||||
* @throws NullPointerException if the generator is null
|
||||
* @since 1.8
|
||||
*/
|
||||
public static void setAll(double[] array, IntToDoubleFunction generator) {
|
||||
Objects.requireNonNull(generator);
|
||||
for (int i = 0; i < array.length; i++)
|
||||
array[i] = generator.applyAsDouble(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all elements of the specified array, in parallel, using the
|
||||
* provided generator function to compute each element.
|
||||
*
|
||||
* <p>If the generator function throws an exception, an unchecked exception
|
||||
* is thrown from {@code parallelSetAll} and the array is left in an
|
||||
* indeterminate state.
|
||||
*
|
||||
* @param array array to be initialized
|
||||
* @param generator a function accepting an index and producing the desired
|
||||
* value for that position
|
||||
* @throws NullPointerException if the generator is null
|
||||
* @since 1.8
|
||||
*/
|
||||
public static void parallelSetAll(double[] array, IntToDoubleFunction generator) {
|
||||
Objects.requireNonNull(generator);
|
||||
IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsDouble(i); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Spliterator} covering all of the specified array.
|
||||
*
|
||||
* <p>The spliterator reports {@link Spliterator#SIZED},
|
||||
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
|
||||
* {@link Spliterator#IMMUTABLE}.
|
||||
*
|
||||
* @param <T> Type of elements
|
||||
* @param array The array, assumed to be unmodified during use
|
||||
* @return A spliterator from the array
|
||||
* @throws NullPointerException if the specified array is {@code null}
|
||||
* @param <T> type of elements
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @return a spliterator for the array elements
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <T> Spliterator<T> spliterator(T[] array) {
|
||||
@ -4325,39 +4493,38 @@ public class Arrays {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Spliterator} covering the specified range of the
|
||||
* Returns a {@link Spliterator} covering the specified range of the
|
||||
* specified array.
|
||||
*
|
||||
* <p>The spliterator reports {@link Spliterator#SIZED},
|
||||
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
|
||||
* {@link Spliterator#IMMUTABLE}.
|
||||
*
|
||||
* @param <T> Type of elements
|
||||
* @param array The array, assumed to be unmodified during use
|
||||
* @param fromIndex The least index (inclusive) to cover
|
||||
* @param toIndex One past the greatest index to cover
|
||||
* @return A spliterator from the array
|
||||
* @throws NullPointerException if the specified array is {@code null}
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
|
||||
* {@code toIndex} is less than {@code fromIndex}, or
|
||||
* {@code toIndex} is greater than the array size
|
||||
* @param <T> type of elements
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param startInclusive the first index to cover, inclusive
|
||||
* @param endExclusive index immediately past the last index to cover
|
||||
* @return a spliterator for the array elements
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
|
||||
* negative, {@code endExclusive} is less than
|
||||
* {@code startInclusive}, or {@code endExclusive} is greater than
|
||||
* the array size
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <T> Spliterator<T> spliterator(T[] array, int fromIndex, int toIndex) {
|
||||
return Spliterators.spliterator(array, fromIndex, toIndex,
|
||||
public static <T> Spliterator<T> spliterator(T[] array, int startInclusive, int endExclusive) {
|
||||
return Spliterators.spliterator(array, startInclusive, endExclusive,
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Spliterator.OfInt} covering all of the specified array.
|
||||
* Returns a {@link Spliterator.OfInt} covering all of the specified array.
|
||||
*
|
||||
* <p>The spliterator reports {@link Spliterator#SIZED},
|
||||
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
|
||||
* {@link Spliterator#IMMUTABLE}.
|
||||
*
|
||||
* @param array The array, assumed to be unmodified during use
|
||||
* @return A spliterator from the array
|
||||
* @throws NullPointerException if the specified array is {@code null}
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @return a spliterator for the array elements
|
||||
* @since 1.8
|
||||
*/
|
||||
public static Spliterator.OfInt spliterator(int[] array) {
|
||||
@ -4366,38 +4533,37 @@ public class Arrays {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Spliterator.OfInt} covering the specified range of the
|
||||
* Returns a {@link Spliterator.OfInt} covering the specified range of the
|
||||
* specified array.
|
||||
*
|
||||
* <p>The spliterator reports {@link Spliterator#SIZED},
|
||||
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
|
||||
* {@link Spliterator#IMMUTABLE}.
|
||||
*
|
||||
* @param array The array, assumed to be unmodified during use
|
||||
* @param fromIndex The least index (inclusive) to cover
|
||||
* @param toIndex One past the greatest index to cover
|
||||
* @return A spliterator from the array
|
||||
* @throws NullPointerException if the specified array is {@code null}
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
|
||||
* {@code toIndex} is less than {@code fromIndex}, or
|
||||
* {@code toIndex} is greater than the array size
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param startInclusive the first index to cover, inclusive
|
||||
* @param endExclusive index immediately past the last index to cover
|
||||
* @return a spliterator for the array elements
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
|
||||
* negative, {@code endExclusive} is less than
|
||||
* {@code startInclusive}, or {@code endExclusive} is greater than
|
||||
* the array size
|
||||
* @since 1.8
|
||||
*/
|
||||
public static Spliterator.OfInt spliterator(int[] array, int fromIndex, int toIndex) {
|
||||
return Spliterators.spliterator(array, fromIndex, toIndex,
|
||||
public static Spliterator.OfInt spliterator(int[] array, int startInclusive, int endExclusive) {
|
||||
return Spliterators.spliterator(array, startInclusive, endExclusive,
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Spliterator.OfLong} covering all of the specified array.
|
||||
* Returns a {@link Spliterator.OfLong} covering all of the specified array.
|
||||
*
|
||||
* <p>The spliterator reports {@link Spliterator#SIZED},
|
||||
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
|
||||
* {@link Spliterator#IMMUTABLE}.
|
||||
*
|
||||
* @param array The array, assumed to be unmodified during use
|
||||
* @return A spliterator from the array
|
||||
* @throws NullPointerException if the specified array is {@code null}
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @return the spliterator for the array elements
|
||||
* @since 1.8
|
||||
*/
|
||||
public static Spliterator.OfLong spliterator(long[] array) {
|
||||
@ -4406,39 +4572,38 @@ public class Arrays {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Spliterator.OfLong} covering the specified range of the
|
||||
* Returns a {@link Spliterator.OfLong} covering the specified range of the
|
||||
* specified array.
|
||||
*
|
||||
* <p>The spliterator reports {@link Spliterator#SIZED},
|
||||
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
|
||||
* {@link Spliterator#IMMUTABLE}.
|
||||
*
|
||||
* @param array The array, assumed to be unmodified during use
|
||||
* @param fromIndex The least index (inclusive) to cover
|
||||
* @param toIndex One past the greatest index to cover
|
||||
* @return A spliterator from the array
|
||||
* @throws NullPointerException if the specified array is {@code null}
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
|
||||
* {@code toIndex} is less than {@code fromIndex}, or
|
||||
* {@code toIndex} is greater than the array size
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param startInclusive the first index to cover, inclusive
|
||||
* @param endExclusive index immediately past the last index to cover
|
||||
* @return a spliterator for the array elements
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
|
||||
* negative, {@code endExclusive} is less than
|
||||
* {@code startInclusive}, or {@code endExclusive} is greater than
|
||||
* the array size
|
||||
* @since 1.8
|
||||
*/
|
||||
public static Spliterator.OfLong spliterator(long[] array, int fromIndex, int toIndex) {
|
||||
return Spliterators.spliterator(array, fromIndex, toIndex,
|
||||
public static Spliterator.OfLong spliterator(long[] array, int startInclusive, int endExclusive) {
|
||||
return Spliterators.spliterator(array, startInclusive, endExclusive,
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Spliterator.OfDouble} covering all of the specified
|
||||
* Returns a {@link Spliterator.OfDouble} covering all of the specified
|
||||
* array.
|
||||
*
|
||||
* <p>The spliterator reports {@link Spliterator#SIZED},
|
||||
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
|
||||
* {@link Spliterator#IMMUTABLE}.
|
||||
*
|
||||
* @param array The array, assumed to be unmodified during use
|
||||
* @return A spliterator from the array
|
||||
* @throws NullPointerException if the specified array is {@code null}
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @return a spliterator for the array elements
|
||||
* @since 1.8
|
||||
*/
|
||||
public static Spliterator.OfDouble spliterator(double[] array) {
|
||||
@ -4447,25 +4612,147 @@ public class Arrays {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Spliterator.OfDouble} covering the specified range of
|
||||
* Returns a {@link Spliterator.OfDouble} covering the specified range of
|
||||
* the specified array.
|
||||
*
|
||||
* <p>The spliterator reports {@link Spliterator#SIZED},
|
||||
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
|
||||
* {@link Spliterator#IMMUTABLE}.
|
||||
*
|
||||
* @param array The array, assumed to be unmodified during use
|
||||
* @param fromIndex The least index (inclusive) to cover
|
||||
* @param toIndex One past the greatest index to cover
|
||||
* @return A spliterator from the array
|
||||
* @throws NullPointerException if the specified array is {@code null}
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
|
||||
* {@code toIndex} is less than {@code fromIndex}, or
|
||||
* {@code toIndex} is greater than the array size
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param startInclusive the first index to cover, inclusive
|
||||
* @param endExclusive index immediately past the last index to cover
|
||||
* @return a spliterator for the array elements
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
|
||||
* negative, {@code endExclusive} is less than
|
||||
* {@code startInclusive}, or {@code endExclusive} is greater than
|
||||
* the array size
|
||||
* @since 1.8
|
||||
*/
|
||||
public static Spliterator.OfDouble spliterator(double[] array, int fromIndex, int toIndex) {
|
||||
return Spliterators.spliterator(array, fromIndex, toIndex,
|
||||
public static Spliterator.OfDouble spliterator(double[] array, int startInclusive, int endExclusive) {
|
||||
return Spliterators.spliterator(array, startInclusive, endExclusive,
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@link Stream} with the specified array as its
|
||||
* source.
|
||||
*
|
||||
* @param <T> The type of the array elements
|
||||
* @param array The array, assumed to be unmodified during use
|
||||
* @return a {@code Stream} for the array
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <T> Stream<T> stream(T[] array) {
|
||||
return stream(array, 0, array.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@link Stream} with the specified range of the
|
||||
* specified array as its source.
|
||||
*
|
||||
* @param <T> the type of the array elements
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param startInclusive the first index to cover, inclusive
|
||||
* @param endExclusive index immediately past the last index to cover
|
||||
* @return a {@code Stream} for the array range
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
|
||||
* negative, {@code endExclusive} is less than
|
||||
* {@code startInclusive}, or {@code endExclusive} is greater than
|
||||
* the array size
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) {
|
||||
return StreamSupport.stream(spliterator(array, startInclusive, endExclusive));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@link IntStream} with the specified array as its
|
||||
* source.
|
||||
*
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @return an {@code IntStream} for the array
|
||||
* @since 1.8
|
||||
*/
|
||||
public static IntStream stream(int[] array) {
|
||||
return stream(array, 0, array.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@link IntStream} with the specified range of the
|
||||
* specified array as its source.
|
||||
*
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param startInclusive the first index to cover, inclusive
|
||||
* @param endExclusive index immediately past the last index to cover
|
||||
* @return an {@code IntStream} for the array range
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
|
||||
* negative, {@code endExclusive} is less than
|
||||
* {@code startInclusive}, or {@code endExclusive} is greater than
|
||||
* the array size
|
||||
* @since 1.8
|
||||
*/
|
||||
public static IntStream stream(int[] array, int startInclusive, int endExclusive) {
|
||||
return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@link LongStream} with the specified array as its
|
||||
* source.
|
||||
*
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @return a {@code LongStream} for the array
|
||||
* @since 1.8
|
||||
*/
|
||||
public static LongStream stream(long[] array) {
|
||||
return stream(array, 0, array.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@link LongStream} with the specified range of the
|
||||
* specified array as its source.
|
||||
*
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param startInclusive the first index to cover, inclusive
|
||||
* @param endExclusive index immediately past the last index to cover
|
||||
* @return a {@code LongStream} for the array range
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
|
||||
* negative, {@code endExclusive} is less than
|
||||
* {@code startInclusive}, or {@code endExclusive} is greater than
|
||||
* the array size
|
||||
* @since 1.8
|
||||
*/
|
||||
public static LongStream stream(long[] array, int startInclusive, int endExclusive) {
|
||||
return StreamSupport.longStream(spliterator(array, startInclusive, endExclusive));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@link DoubleStream} with the specified array as its
|
||||
* source.
|
||||
*
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @return a {@code DoubleStream} for the array
|
||||
* @since 1.8
|
||||
*/
|
||||
public static DoubleStream stream(double[] array) {
|
||||
return stream(array, 0, array.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@link DoubleStream} with the specified range of the
|
||||
* specified array as its source.
|
||||
*
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param startInclusive the first index to cover, inclusive
|
||||
* @param endExclusive index immediately past the last index to cover
|
||||
* @return a {@code DoubleStream} for the array range
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is
|
||||
* negative, {@code endExclusive} is less than
|
||||
* {@code startInclusive}, or {@code endExclusive} is greater than
|
||||
* the array size
|
||||
* @since 1.8
|
||||
*/
|
||||
public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {
|
||||
return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive));
|
||||
}
|
||||
}
|
||||
|
||||
1320
jdk/src/share/classes/java/util/stream/Collectors.java
Normal file
1320
jdk/src/share/classes/java/util/stream/Collectors.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -24,15 +24,19 @@
|
||||
*/
|
||||
package java.util.stream;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.DoubleSummaryStatistics;
|
||||
import java.util.Objects;
|
||||
import java.util.OptionalDouble;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.DoubleBinaryOperator;
|
||||
import java.util.function.DoubleConsumer;
|
||||
import java.util.function.DoubleFunction;
|
||||
import java.util.function.DoublePredicate;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.function.DoubleToIntFunction;
|
||||
import java.util.function.DoubleToLongFunction;
|
||||
import java.util.function.DoubleUnaryOperator;
|
||||
@ -649,4 +653,175 @@ public interface DoubleStream extends BaseStream<Double, DoubleStream> {
|
||||
|
||||
@Override
|
||||
Spliterator.OfDouble spliterator();
|
||||
|
||||
|
||||
// Static factories
|
||||
|
||||
/**
|
||||
* Returns a builder for a {@code DoubleStream}.
|
||||
*
|
||||
* @return a stream builder
|
||||
*/
|
||||
public static StreamBuilder.OfDouble builder() {
|
||||
return new Streams.DoubleStreamBuilderImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty sequential {@code DoubleStream}.
|
||||
*
|
||||
* @return an empty sequential stream
|
||||
*/
|
||||
public static DoubleStream empty() {
|
||||
return StreamSupport.doubleStream(Spliterators.emptyDoubleSpliterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code DoubleStream} containing a single element.
|
||||
*
|
||||
* @param t the single element
|
||||
* @return a singleton sequential stream
|
||||
*/
|
||||
public static DoubleStream of(double t) {
|
||||
return StreamSupport.doubleStream(new Streams.DoubleStreamBuilderImpl(t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential stream whose elements are the specified values.
|
||||
*
|
||||
* @param values the elements of the new stream
|
||||
* @return the new stream
|
||||
*/
|
||||
public static DoubleStream of(double... values) {
|
||||
return Arrays.stream(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite sequential {@code DoubleStream} produced by iterative
|
||||
* application of a function {@code f} to an initial element {@code seed},
|
||||
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
|
||||
* {@code f(f(seed))}, etc.
|
||||
*
|
||||
* <p>The first element (position {@code 0}) in the {@code DoubleStream}
|
||||
* will be the provided {@code seed}. For {@code n > 0}, the element at
|
||||
* position {@code n}, will be the result of applying the function {@code f}
|
||||
* to the element at position {@code n - 1}.
|
||||
*
|
||||
* @param seed the initial element
|
||||
* @param f a function to be applied to to the previous element to produce
|
||||
* a new element
|
||||
* @return a new sequential {@code DoubleStream}
|
||||
*/
|
||||
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
|
||||
Objects.requireNonNull(f);
|
||||
final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
|
||||
double t = seed;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double nextDouble() {
|
||||
double v = t;
|
||||
t = f.applyAsDouble(t);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
|
||||
iterator,
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code DoubleStream} where each element is
|
||||
* generated by an {@code DoubleSupplier}. This is suitable for generating
|
||||
* constant streams, streams of random elements, etc.
|
||||
*
|
||||
* @param s the {@code DoubleSupplier} for generated elements
|
||||
* @return a new sequential {@code DoubleStream}
|
||||
*/
|
||||
public static DoubleStream generate(DoubleSupplier s) {
|
||||
Objects.requireNonNull(s);
|
||||
return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
|
||||
new PrimitiveIterator.OfDouble() {
|
||||
@Override
|
||||
public boolean hasNext() { return true; }
|
||||
|
||||
@Override
|
||||
public double nextDouble() { return s.getAsDouble(); }
|
||||
},
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code DoubleStream} from {@code startInclusive} (inclusive)
|
||||
* to {@code endExclusive} (exclusive) by an incremental step of 1.0.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* doubleRange(startInclusive, endExclusive, 1.0);
|
||||
* }</pre>
|
||||
*
|
||||
* @param startInclusive the (inclusive) initial value
|
||||
* @param endExclusive the exclusive upper bound
|
||||
* @return a sequential {@code DoubleStream} for the range of {@code double}
|
||||
* elements
|
||||
*/
|
||||
public static DoubleStream range(double startInclusive, double endExclusive) {
|
||||
return range(startInclusive, endExclusive, 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code DoubleStream} from {@code startInclusive}
|
||||
* (inclusive) to {@code endExclusive} (exclusive) by {@code step}. If
|
||||
* {@code startInclusive} is greater than or equal to {@code
|
||||
* endExclusive}, an empty stream is returned.
|
||||
*
|
||||
* An equivalent sequence of increasing values can be produced
|
||||
* sequentially using a {@code for} loop as follows:
|
||||
* <pre>{@code
|
||||
* long size = (long) Math.ceil((startInclusive - endExclusive) / step);
|
||||
* long i = 0
|
||||
* for (double v = startInclusive; i < size; i++, v = startInclusive + step * i) {
|
||||
* ...
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param startInclusive the (inclusive) initial value
|
||||
* @param endExclusive the exclusive upper bound
|
||||
* @param step the difference between consecutive values
|
||||
* @return a sequential {@code DoubleStream} for tne range of {@code double}
|
||||
* elements
|
||||
* @throws IllegalArgumentException if {@code step} is less than or equal to
|
||||
* 0. is {@code NaN}, or the count of elements in the range would be
|
||||
* greater than {@code Long.MAX_VALUE}
|
||||
*/
|
||||
public static DoubleStream range(double startInclusive, double endExclusive, double step) {
|
||||
// @@@ Need to check for ranges that may not produce distinct values
|
||||
// such as when the step is very small
|
||||
// Also clarify the size of the range which may produce more or less
|
||||
// than expected
|
||||
if (step <= 0 || Double.isNaN(step)) {
|
||||
throw new IllegalArgumentException(String.format("Illegal step: %f", step));
|
||||
} else {
|
||||
double range = endExclusive - startInclusive;
|
||||
if (range <= 0) {
|
||||
return empty();
|
||||
}
|
||||
double size = Math.ceil((endExclusive - startInclusive) / step);
|
||||
if (Double.isNaN(size)) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Illegal range: %f size is NaN", size));
|
||||
} else if (size > Long.MAX_VALUE) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Illegal range: size %f > Long.MAX_VALUE", size));
|
||||
} else {
|
||||
return StreamSupport.doubleStream(
|
||||
new Streams.RangeDoubleSpliterator(
|
||||
startInclusive, endExclusive, step, 0, (long) size));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,17 +24,21 @@
|
||||
*/
|
||||
package java.util.stream;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.IntSummaryStatistics;
|
||||
import java.util.Objects;
|
||||
import java.util.OptionalDouble;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.function.IntPredicate;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.IntToDoubleFunction;
|
||||
import java.util.function.IntToLongFunction;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
@ -652,4 +656,153 @@ public interface IntStream extends BaseStream<Integer, IntStream> {
|
||||
|
||||
@Override
|
||||
Spliterator.OfInt spliterator();
|
||||
|
||||
// Static factories
|
||||
|
||||
/**
|
||||
* Returns a builder for an {@code IntStream}.
|
||||
*
|
||||
* @return a stream builder
|
||||
*/
|
||||
public static StreamBuilder.OfInt builder() {
|
||||
return new Streams.IntStreamBuilderImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty sequential {@code IntStream}.
|
||||
*
|
||||
* @return an empty sequential stream
|
||||
*/
|
||||
public static IntStream empty() {
|
||||
return StreamSupport.intStream(Spliterators.emptyIntSpliterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code IntStream} containing a single element.
|
||||
*
|
||||
* @param t the single element
|
||||
* @return a singleton sequential stream
|
||||
*/
|
||||
public static IntStream of(int t) {
|
||||
return StreamSupport.intStream(new Streams.IntStreamBuilderImpl(t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential stream whose elements are the specified values.
|
||||
*
|
||||
* @param values the elements of the new stream
|
||||
* @return the new stream
|
||||
*/
|
||||
public static IntStream of(int... values) {
|
||||
return Arrays.stream(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite sequential {@code IntStream} produced by iterative
|
||||
* application of a function {@code f} to an initial element {@code seed},
|
||||
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
|
||||
* {@code f(f(seed))}, etc.
|
||||
*
|
||||
* <p>The first element (position {@code 0}) in the {@code IntStream} will be
|
||||
* the provided {@code seed}. For {@code n > 0}, the element at position
|
||||
* {@code n}, will be the result of applying the function {@code f} to the
|
||||
* element at position {@code n - 1}.
|
||||
*
|
||||
* @param seed the initial element
|
||||
* @param f a function to be applied to to the previous element to produce
|
||||
* a new element
|
||||
* @return A new sequential {@code IntStream}
|
||||
*/
|
||||
public static IntStream iterate(final int seed, final IntUnaryOperator f) {
|
||||
Objects.requireNonNull(f);
|
||||
final PrimitiveIterator.OfInt iterator = new PrimitiveIterator.OfInt() {
|
||||
int t = seed;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextInt() {
|
||||
int v = t;
|
||||
t = f.applyAsInt(t);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
return StreamSupport.intStream(Spliterators.spliteratorUnknownSize(
|
||||
iterator,
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code IntStream} where each element is
|
||||
* generated by an {@code IntSupplier}. This is suitable for generating
|
||||
* constant streams, streams of random elements, etc.
|
||||
*
|
||||
* @param s the {@code IntSupplier} for generated elements
|
||||
* @return a new sequential {@code IntStream}
|
||||
*/
|
||||
public static IntStream generate(IntSupplier s) {
|
||||
Objects.requireNonNull(s);
|
||||
return StreamSupport.intStream(Spliterators.spliteratorUnknownSize(
|
||||
new PrimitiveIterator.OfInt() {
|
||||
@Override
|
||||
public boolean hasNext() { return true; }
|
||||
|
||||
@Override
|
||||
public int nextInt() { return s.getAsInt(); }
|
||||
},
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code IntStream} from {@code startInclusive}
|
||||
* (inclusive) to {@code endExclusive} (exclusive) by an incremental step of
|
||||
* 1.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* intRange(startInclusive, endExclusive, 1);
|
||||
* }</pre>
|
||||
*
|
||||
* @param startInclusive the (inclusive) initial value
|
||||
* @param endExclusive the exclusive upper bound
|
||||
* @return a sequential {@code IntStream} for the range of {@code int}
|
||||
* elements
|
||||
*/
|
||||
public static IntStream range(int startInclusive, int endExclusive) {
|
||||
return range(startInclusive, endExclusive, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code IntStream} from {@code startInclusive}
|
||||
* (inclusive) to {@code endExclusive} (exclusive) by a positive {@code
|
||||
* step}. If {@code startInclusive} is greater than or equal to {@code
|
||||
* endExclusive}, an empty stream is returned.
|
||||
*
|
||||
* <p>An equivalent sequence of increasing values can be produced
|
||||
* sequentially using a {@code for} loop as follows:
|
||||
* <pre>{@code
|
||||
* for (int i = startInclusive; i < endExclusive ; i += step) { ... }
|
||||
* }</pre>
|
||||
*
|
||||
* @param startInclusive the (inclusive) initial value
|
||||
* @param endExclusive the exclusive upper bound
|
||||
* @param step the positive difference between consecutive values
|
||||
* @return a sequential {@code IntStream} for the range of {@code int}
|
||||
* elements
|
||||
* @throws IllegalArgumentException if {@code step} is less than or equal to
|
||||
* 0
|
||||
*/
|
||||
public static IntStream range(int startInclusive, int endExclusive, int step) {
|
||||
if (step <= 0) {
|
||||
throw new IllegalArgumentException(String.format("Illegal step: %d", step));
|
||||
} else if (startInclusive >= endExclusive) {
|
||||
return empty();
|
||||
} else {
|
||||
return StreamSupport.intStream(new Streams.RangeIntSpliterator(startInclusive, endExclusive, step));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,17 +24,21 @@
|
||||
*/
|
||||
package java.util.stream;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LongSummaryStatistics;
|
||||
import java.util.Objects;
|
||||
import java.util.OptionalDouble;
|
||||
import java.util.OptionalLong;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import java.util.function.LongConsumer;
|
||||
import java.util.function.LongFunction;
|
||||
import java.util.function.LongPredicate;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.function.LongToDoubleFunction;
|
||||
import java.util.function.LongToIntFunction;
|
||||
import java.util.function.LongUnaryOperator;
|
||||
@ -643,4 +647,153 @@ public interface LongStream extends BaseStream<Long, LongStream> {
|
||||
|
||||
@Override
|
||||
Spliterator.OfLong spliterator();
|
||||
|
||||
// Static factories
|
||||
|
||||
/**
|
||||
* Returns a builder for a {@code LongStream}.
|
||||
*
|
||||
* @return a stream builder
|
||||
*/
|
||||
public static StreamBuilder.OfLong builder() {
|
||||
return new Streams.LongStreamBuilderImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty sequential {@code LongStream}.
|
||||
*
|
||||
* @return an empty sequential stream
|
||||
*/
|
||||
public static LongStream empty() {
|
||||
return StreamSupport.longStream(Spliterators.emptyLongSpliterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code LongStream} containing a single element.
|
||||
*
|
||||
* @param t the single element
|
||||
* @return a singleton sequential stream
|
||||
*/
|
||||
public static LongStream of(long t) {
|
||||
return StreamSupport.longStream(new Streams.LongStreamBuilderImpl(t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential stream whose elements are the specified values.
|
||||
*
|
||||
* @param values the elements of the new stream
|
||||
* @return the new stream
|
||||
*/
|
||||
public static LongStream of(long... values) {
|
||||
return Arrays.stream(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite sequential {@code LongStream} produced by iterative
|
||||
* application of a function {@code f} to an initial element {@code seed},
|
||||
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
|
||||
* {@code f(f(seed))}, etc.
|
||||
*
|
||||
* <p>The first element (position {@code 0}) in the {@code LongStream} will
|
||||
* be the provided {@code seed}. For {@code n > 0}, the element at position
|
||||
* {@code n}, will be the result of applying the function {@code f} to the
|
||||
* element at position {@code n - 1}.
|
||||
*
|
||||
* @param seed the initial element
|
||||
* @param f a function to be applied to to the previous element to produce
|
||||
* a new element
|
||||
* @return a new sequential {@code LongStream}
|
||||
*/
|
||||
public static LongStream iterate(final long seed, final LongUnaryOperator f) {
|
||||
Objects.requireNonNull(f);
|
||||
final PrimitiveIterator.OfLong iterator = new PrimitiveIterator.OfLong() {
|
||||
long t = seed;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextLong() {
|
||||
long v = t;
|
||||
t = f.applyAsLong(t);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
return StreamSupport.longStream(Spliterators.spliteratorUnknownSize(
|
||||
iterator,
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code LongStream} where each element is generated
|
||||
* by a {@code LongSupplier}. This is suitable for generating constant
|
||||
* streams, streams of random elements, etc.
|
||||
*
|
||||
* @param s the {@code LongSupplier} for generated elements
|
||||
* @return a new sequential {@code LongStream}
|
||||
*/
|
||||
public static LongStream generate(LongSupplier s) {
|
||||
Objects.requireNonNull(s);
|
||||
return StreamSupport.longStream(Spliterators.spliteratorUnknownSize(
|
||||
new PrimitiveIterator.OfLong() {
|
||||
@Override
|
||||
public boolean hasNext() { return true; }
|
||||
|
||||
@Override
|
||||
public long nextLong() { return s.getAsLong(); }
|
||||
},
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code LongStream} from {@code startInclusive}
|
||||
* (inclusive) to {@code endExclusive} (exclusive) by an incremental step of
|
||||
* 1.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* longRange(startInclusive, endExclusive, 1);
|
||||
* }</pre>
|
||||
*
|
||||
* @param startInclusive the (inclusive) initial value
|
||||
* @param endExclusive the exclusive upper bound
|
||||
* @return a sequential {@code LongStream} for the range of {@code long}
|
||||
* elements
|
||||
*/
|
||||
public static LongStream range(long startInclusive, final long endExclusive) {
|
||||
return range(startInclusive, endExclusive, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code LongStream} from {@code startInclusive}
|
||||
* (inclusive) to {@code endExclusive} (exclusive) by {@code step}. If
|
||||
* {@code startInclusive} is greater than or equal to {@code
|
||||
* endExclusive}, an empty stream is returned.
|
||||
*
|
||||
* <p>An equivalent sequence of increasing values can be produced
|
||||
* sequentially using a {@code for} loop as follows:
|
||||
* <pre>{@code
|
||||
* for (long i = startInclusive; i < endExclusive ; i += step) { ... }
|
||||
* }</pre>
|
||||
*
|
||||
* @param startInclusive the (inclusive) initial value
|
||||
* @param endExclusive the exclusive upper bound
|
||||
* @param step the difference between consecutive values
|
||||
* @return a sequential {@code LongStream} for the range of {@code long}
|
||||
* elements
|
||||
* @throws IllegalArgumentException if {@code step} is less than or equal to
|
||||
* 0
|
||||
*/
|
||||
public static LongStream range(long startInclusive, final long endExclusive, final long step) {
|
||||
if (step <= 0) {
|
||||
throw new IllegalArgumentException(String.format("Illegal step: %d", step));
|
||||
} else if (startInclusive >= endExclusive) {
|
||||
return empty();
|
||||
} else {
|
||||
return StreamSupport.longStream(new Streams.RangeLongSpliterator(startInclusive, endExclusive, step));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,8 +24,13 @@
|
||||
*/
|
||||
package java.util.stream;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BinaryOperator;
|
||||
@ -37,6 +42,7 @@ import java.util.function.Supplier;
|
||||
import java.util.function.ToDoubleFunction;
|
||||
import java.util.function.ToIntFunction;
|
||||
import java.util.function.ToLongFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
// @@@ Specification to-do list @@@
|
||||
// - Describe the difference between sequential and parallel streams
|
||||
@ -779,4 +785,109 @@ public interface Stream<T> extends BaseStream<T, Stream<T>> {
|
||||
* @see #findFirst()
|
||||
*/
|
||||
Optional<T> findAny();
|
||||
|
||||
// Static factories
|
||||
|
||||
/**
|
||||
* Returns a builder for a {@code Stream}.
|
||||
*
|
||||
* @param <T> type of elements
|
||||
* @return a stream builder
|
||||
*/
|
||||
public static<T> StreamBuilder<T> builder() {
|
||||
return new Streams.StreamBuilderImpl<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty sequential {@code Stream}.
|
||||
*
|
||||
* @param <T> the type of stream elements
|
||||
* @return an empty sequential stream
|
||||
*/
|
||||
public static<T> Stream<T> empty() {
|
||||
return StreamSupport.stream(Spliterators.<T>emptySpliterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code Stream} containing a single element.
|
||||
*
|
||||
* @param t the single element
|
||||
* @param <T> the type of stream elements
|
||||
* @return a singleton sequential stream
|
||||
*/
|
||||
public static<T> Stream<T> of(T t) {
|
||||
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential stream whose elements are the specified values.
|
||||
*
|
||||
* @param <T> the type of stream elements
|
||||
* @param values the elements of the new stream
|
||||
* @return the new stream
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static<T> Stream<T> of(T... values) {
|
||||
return Arrays.stream(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an infinite sequential {@code Stream} produced by iterative
|
||||
* application of a function {@code f} to an initial element {@code seed},
|
||||
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
|
||||
* {@code f(f(seed))}, etc.
|
||||
*
|
||||
* <p>The first element (position {@code 0}) in the {@code Stream} will be
|
||||
* the provided {@code seed}. For {@code n > 0}, the element at position
|
||||
* {@code n}, will be the result of applying the function {@code f} to the
|
||||
* element at position {@code n - 1}.
|
||||
*
|
||||
* @param <T> the type of stream elements
|
||||
* @param seed the initial element
|
||||
* @param f a function to be applied to to the previous element to produce
|
||||
* a new element
|
||||
* @return a new sequential {@code Stream}
|
||||
*/
|
||||
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
|
||||
Objects.requireNonNull(f);
|
||||
final Iterator<T> iterator = new Iterator<T>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
T t = (T) Streams.NONE;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return t = (t == Streams.NONE) ? seed : f.apply(t);
|
||||
}
|
||||
};
|
||||
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
|
||||
iterator,
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequential {@code Stream} where each element is
|
||||
* generated by a {@code Supplier}. This is suitable for generating
|
||||
* constant streams, streams of random elements, etc.
|
||||
*
|
||||
* @param <T> the type of stream elements
|
||||
* @param s the {@code Supplier} of generated elements
|
||||
* @return a new sequential {@code Stream}
|
||||
*/
|
||||
public static<T> Stream<T> generate(Supplier<T> s) {
|
||||
Objects.requireNonNull(s);
|
||||
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
|
||||
new Iterator<T>() {
|
||||
@Override
|
||||
public boolean hasNext() { return true; }
|
||||
|
||||
@Override
|
||||
public T next() { return s.get(); }
|
||||
},
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE));
|
||||
}
|
||||
}
|
||||
|
||||
265
jdk/src/share/classes/java/util/stream/StreamBuilder.java
Normal file
265
jdk/src/share/classes/java/util/stream/StreamBuilder.java
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package java.util.stream;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.DoubleConsumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.LongConsumer;
|
||||
|
||||
/**
|
||||
* A mutable builder for a {@code Stream}. This allows the creation of a
|
||||
* {@code Stream} by generating elements individually and adding them to the
|
||||
* {@code StreamBuilder} (without the copying overhead that comes from using
|
||||
* an {@code ArrayList} as a temporary buffer.)
|
||||
*
|
||||
* <p>A {@code StreamBuilder} has a lifecycle, where it starts in a building
|
||||
* phase, during which elements can be added, and then transitions to a built
|
||||
* phase, after which elements may not be added. The built phase begins
|
||||
* when the {@link #build()}} method is called, which creates an ordered
|
||||
* {@code Stream} whose elements are the elements that were added to the stream
|
||||
* builder, in the order they were added.
|
||||
*
|
||||
* <p>Primitive specializations of {@code StreamBuilder} are provided
|
||||
* for {@link OfInt int}, {@link OfLong long}, and {@link OfDouble double}
|
||||
* values.
|
||||
*
|
||||
* @param <T> the type of stream elements
|
||||
* @see Stream#builder()
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface StreamBuilder<T> extends Consumer<T> {
|
||||
|
||||
/**
|
||||
* Adds an element to the stream being built.
|
||||
*
|
||||
* @throws IllegalStateException if the builder has already transitioned to
|
||||
* the built state
|
||||
*/
|
||||
@Override
|
||||
void accept(T t);
|
||||
|
||||
/**
|
||||
* Adds an element to the stream being built.
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* accept(t)
|
||||
* return this;
|
||||
* }</pre>
|
||||
*
|
||||
* @param t the element to add
|
||||
* @return {@code this} builder
|
||||
* @throws IllegalStateException if the builder has already transitioned to
|
||||
* the built state
|
||||
*/
|
||||
default StreamBuilder<T> add(T t) {
|
||||
accept(t);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the stream, transitioning this builder to the built state.
|
||||
* An {@code IllegalStateException} is thrown if there are further attempts
|
||||
* to operate on the builder after it has entered the built state.
|
||||
*
|
||||
* @return the built stream
|
||||
* @throws IllegalStateException if the builder has already transitioned to
|
||||
* the built state
|
||||
*/
|
||||
Stream<T> build();
|
||||
|
||||
/**
|
||||
* A mutable builder for an {@code IntStream}.
|
||||
*
|
||||
* <p>A stream builder has a lifecycle, where it starts in a building
|
||||
* phase, during which elements can be added, and then transitions to a
|
||||
* built phase, after which elements may not be added. The built phase
|
||||
* begins when the {@link #build()}} method is called, which creates an
|
||||
* ordered stream whose elements are the elements that were added to the
|
||||
* stream builder, in the order they were added.
|
||||
*
|
||||
* @see IntStream#builder()
|
||||
* @since 1.8
|
||||
*/
|
||||
interface OfInt extends IntConsumer {
|
||||
|
||||
/**
|
||||
* Adds an element to the stream being built.
|
||||
*
|
||||
* @throws IllegalStateException if the builder has already transitioned
|
||||
* to the built state
|
||||
*/
|
||||
@Override
|
||||
void accept(int t);
|
||||
|
||||
/**
|
||||
* Adds an element to the stream being built.
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* accept(t)
|
||||
* return this;
|
||||
* }</pre>
|
||||
*
|
||||
* @param t the element to add
|
||||
* @return {@code this} builder
|
||||
* @throws IllegalStateException if the builder has already transitioned
|
||||
* to the built state
|
||||
*/
|
||||
default StreamBuilder.OfInt add(int t) {
|
||||
accept(t);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the stream, transitioning this builder to the built state.
|
||||
* An {@code IllegalStateException} is thrown if there are further
|
||||
* attempts to operate on the builder after it has entered the built
|
||||
* state.
|
||||
*
|
||||
* @return the built stream
|
||||
* @throws IllegalStateException if the builder has already transitioned to
|
||||
* the built state
|
||||
*/
|
||||
IntStream build();
|
||||
}
|
||||
|
||||
/**
|
||||
* A mutable builder for a {@code LongStream}.
|
||||
*
|
||||
* <p>A stream builder has a lifecycle, where it starts in a building
|
||||
* phase, during which elements can be added, and then transitions to a
|
||||
* built phase, after which elements may not be added. The built phase
|
||||
* begins when the {@link #build()}} method is called, which creates an
|
||||
* ordered stream whose elements are the elements that were added to the
|
||||
* stream builder, in the order they were added.
|
||||
*
|
||||
* @see LongStream#builder()
|
||||
* @since 1.8
|
||||
*/
|
||||
interface OfLong extends LongConsumer {
|
||||
|
||||
/**
|
||||
* Adds an element to the stream being built.
|
||||
*
|
||||
* @throws IllegalStateException if the builder has already transitioned
|
||||
* to the built state
|
||||
*/
|
||||
@Override
|
||||
void accept(long t);
|
||||
|
||||
/**
|
||||
* Adds an element to the stream being built.
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* accept(t)
|
||||
* return this;
|
||||
* }</pre>
|
||||
*
|
||||
* @param t the element to add
|
||||
* @return {@code this} builder
|
||||
* @throws IllegalStateException if the builder has already transitioned
|
||||
* to the built state
|
||||
*/
|
||||
default StreamBuilder.OfLong add(long t) {
|
||||
accept(t);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the stream, transitioning this builder to the built state.
|
||||
* An {@code IllegalStateException} is thrown if there are further
|
||||
* attempts to operate on the builder after it has entered the built
|
||||
* state.
|
||||
*
|
||||
* @return the built stream
|
||||
* @throws IllegalStateException if the builder has already transitioned
|
||||
* to the built state
|
||||
*/
|
||||
LongStream build();
|
||||
}
|
||||
|
||||
/**
|
||||
* A mutable builder for a {@code DoubleStream}.
|
||||
*
|
||||
* @see LongStream#builder()
|
||||
* @since 1.8
|
||||
*/
|
||||
interface OfDouble extends DoubleConsumer {
|
||||
|
||||
/**
|
||||
* Adds an element to the stream being built.
|
||||
*
|
||||
* <p>A stream builder has a lifecycle, where it starts in a building
|
||||
* phase, during which elements can be added, and then transitions to a
|
||||
* built phase, after which elements may not be added. The built phase
|
||||
* begins when the {@link #build()}} method is called, which creates an
|
||||
* ordered stream whose elements are the elements that were added to the
|
||||
* stream builder, in the order they were added.
|
||||
*
|
||||
* @throws IllegalStateException if the builder has already transitioned
|
||||
* to the built state
|
||||
*/
|
||||
@Override
|
||||
void accept(double t);
|
||||
|
||||
/**
|
||||
* Adds an element to the stream being built.
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* accept(t)
|
||||
* return this;
|
||||
* }</pre>
|
||||
*
|
||||
* @param t the element to add
|
||||
* @return {@code this} builder
|
||||
* @throws IllegalStateException if the builder has already transitioned
|
||||
* to the built state
|
||||
*/
|
||||
default StreamBuilder.OfDouble add(double t) {
|
||||
accept(t);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the stream, transitioning this builder to the built state.
|
||||
* An {@code IllegalStateException} is thrown if there are further
|
||||
* attempts to operate on the builder after it has entered the built
|
||||
* state.
|
||||
*
|
||||
* @return the built stream
|
||||
* @throws IllegalStateException if the builder has already transitioned
|
||||
* to the built state
|
||||
*/
|
||||
DoubleStream build();
|
||||
}
|
||||
}
|
||||
656
jdk/src/share/classes/java/util/stream/Streams.java
Normal file
656
jdk/src/share/classes/java/util/stream/Streams.java
Normal file
@ -0,0 +1,656 @@
|
||||
/*
|
||||
* 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package java.util.stream;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.DoubleConsumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.LongConsumer;
|
||||
|
||||
/**
|
||||
* Utility methods for operating on and creating streams.
|
||||
*
|
||||
* <p>Unless otherwise stated, streams are created as sequential streams. A
|
||||
* sequential stream can be transformed into a parallel stream by calling the
|
||||
* {@code parallel()} method on the created stream.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
class Streams {
|
||||
|
||||
private Streams() {
|
||||
throw new Error("no instances");
|
||||
}
|
||||
|
||||
/**
|
||||
* An object instance representing no value, that cannot be an actual
|
||||
* data element of a stream. Used when processing streams that can contain
|
||||
* {@code null} elements to distinguish between a {@code null} value and no
|
||||
* value.
|
||||
*/
|
||||
static final Object NONE = new Object();
|
||||
|
||||
/**
|
||||
* An {@code int} range spliterator.
|
||||
*/
|
||||
static final class RangeIntSpliterator implements Spliterator.OfInt {
|
||||
private int from;
|
||||
private final int upTo;
|
||||
private final int step;
|
||||
|
||||
RangeIntSpliterator(int from, int upTo, int step) {
|
||||
this.from = from;
|
||||
this.upTo = upTo;
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(IntConsumer consumer) {
|
||||
boolean hasNext = from < upTo;
|
||||
if (hasNext) {
|
||||
consumer.accept(from);
|
||||
from += step;
|
||||
}
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(IntConsumer consumer) {
|
||||
int hUpTo = upTo;
|
||||
int hStep = step; // hoist accesses and checks from loop
|
||||
for (int i = from; i < hUpTo; i += hStep)
|
||||
consumer.accept(i);
|
||||
from = upTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() {
|
||||
int d = upTo - from;
|
||||
return (d / step) + ((d % step == 0) ? 0 : 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
|
||||
Spliterator.IMMUTABLE | Spliterator.NONNULL |
|
||||
Spliterator.DISTINCT | Spliterator.SORTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator<? super Integer> getComparator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator.OfInt trySplit() {
|
||||
return estimateSize() <= 1
|
||||
? null
|
||||
: new RangeIntSpliterator(from, from = from + midPoint(), step);
|
||||
}
|
||||
|
||||
private int midPoint() {
|
||||
// Size is known to be >= 2
|
||||
int bisection = (upTo - from) / 2;
|
||||
// If bisection > step then round down to nearest multiple of step
|
||||
// otherwise round up to step
|
||||
return bisection > step ? bisection - bisection % step : step;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@code long} range spliterator.
|
||||
*/
|
||||
static final class RangeLongSpliterator implements Spliterator.OfLong {
|
||||
private long from;
|
||||
private final long upTo;
|
||||
private final long step;
|
||||
|
||||
RangeLongSpliterator(long from, long upTo, long step) {
|
||||
this.from = from;
|
||||
this.upTo = upTo;
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(LongConsumer consumer) {
|
||||
boolean hasNext = from < upTo;
|
||||
if (hasNext) {
|
||||
consumer.accept(from);
|
||||
from += step;
|
||||
}
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(LongConsumer consumer) {
|
||||
long hUpTo = upTo;
|
||||
long hStep = step; // hoist accesses and checks from loop
|
||||
for (long i = from; i < hUpTo; i += hStep)
|
||||
consumer.accept(i);
|
||||
from = upTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() {
|
||||
long d = upTo - from;
|
||||
return (d / step) + ((d % step == 0) ? 0 : 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
|
||||
Spliterator.IMMUTABLE | Spliterator.NONNULL |
|
||||
Spliterator.DISTINCT | Spliterator.SORTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator<? super Long> getComparator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator.OfLong trySplit() {
|
||||
return estimateSize() <= 1
|
||||
? null
|
||||
: new RangeLongSpliterator(from, from = from + midPoint(), step);
|
||||
}
|
||||
|
||||
private long midPoint() {
|
||||
// Size is known to be >= 2
|
||||
long bisection = (upTo - from) / 2;
|
||||
// If bisection > step then round down to nearest multiple of step
|
||||
// otherwise round up to step
|
||||
return bisection > step ? bisection - bisection % step : step;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@code double} range spliterator.
|
||||
*
|
||||
* <p>The traversing and splitting logic is equivalent to that of
|
||||
* {@code RangeLongSpliterator} for increasing values with a {@code step} of
|
||||
* {@code 1}.
|
||||
*
|
||||
* <p>A {@code double} value is calculated from the function
|
||||
* {@code start + i * step} where {@code i} is the absolute position of the
|
||||
* value when traversing an instance of this class that has not been split.
|
||||
* This ensures the same values are produced at the same absolute positions
|
||||
* regardless of how an instance of this class is split or traversed.
|
||||
*/
|
||||
static final class RangeDoubleSpliterator implements Spliterator.OfDouble {
|
||||
private final double from;
|
||||
private final double upTo;
|
||||
private final double step;
|
||||
|
||||
private long lFrom;
|
||||
private final long lUpTo;
|
||||
|
||||
RangeDoubleSpliterator(double from, double upTo, double step, long lFrom, long lUpTo) {
|
||||
this.from = from;
|
||||
this.upTo = upTo;
|
||||
this.step = step;
|
||||
this.lFrom = lFrom;
|
||||
this.lUpTo = lUpTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(DoubleConsumer consumer) {
|
||||
boolean hasNext = lFrom < lUpTo;
|
||||
if (hasNext) {
|
||||
consumer.accept(from + lFrom * step);
|
||||
lFrom++;
|
||||
}
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(DoubleConsumer consumer) {
|
||||
double hOrigin = from;
|
||||
double hStep = step;
|
||||
long hLUpTo = lUpTo;
|
||||
long i = lFrom;
|
||||
for (; i < hLUpTo; i++) {
|
||||
consumer.accept(hOrigin + i * hStep);
|
||||
}
|
||||
lFrom = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() {
|
||||
return lUpTo - lFrom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
|
||||
Spliterator.IMMUTABLE | Spliterator.NONNULL |
|
||||
Spliterator.DISTINCT | Spliterator.SORTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator<? super Double> getComparator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator.OfDouble trySplit() {
|
||||
return estimateSize() <= 1
|
||||
? null
|
||||
: new RangeDoubleSpliterator(from, upTo, step, lFrom, lFrom = lFrom + midPoint());
|
||||
}
|
||||
|
||||
private long midPoint() {
|
||||
// Size is known to be >= 2
|
||||
return (lUpTo - lFrom) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class AbstractStreamBuilderImpl<T, S extends Spliterator<T>> implements Spliterator<T> {
|
||||
// >= 0 when building, < 0 when built
|
||||
// -1 == no elements
|
||||
// -2 == one element, held by first
|
||||
// -3 == two or more elements, held by buffer
|
||||
int count;
|
||||
|
||||
// Spliterator implementation for 0 or 1 element
|
||||
// count == -1 for no elements
|
||||
// count == -2 for one element held by first
|
||||
|
||||
@Override
|
||||
public S trySplit() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() {
|
||||
return -count - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return Spliterator.SIZED | Spliterator.SUBSIZED |
|
||||
Spliterator.ORDERED | Spliterator.IMMUTABLE;
|
||||
}
|
||||
}
|
||||
|
||||
static final class StreamBuilderImpl<T>
|
||||
extends AbstractStreamBuilderImpl<T, Spliterator<T>>
|
||||
implements StreamBuilder<T> {
|
||||
// The first element in the stream
|
||||
// valid if count == 1
|
||||
T first;
|
||||
|
||||
// The first and subsequent elements in the stream
|
||||
// non-null if count == 2
|
||||
SpinedBuffer<T> buffer;
|
||||
|
||||
/**
|
||||
* Constructor for building a stream of 0 or more elements.
|
||||
*/
|
||||
StreamBuilderImpl() { }
|
||||
|
||||
/**
|
||||
* Constructor for a singleton stream.
|
||||
*
|
||||
* @param t the single element
|
||||
*/
|
||||
StreamBuilderImpl(T t) {
|
||||
first = t;
|
||||
count = -2;
|
||||
}
|
||||
|
||||
// StreamBuilder implementation
|
||||
|
||||
@Override
|
||||
public void accept(T t) {
|
||||
if (count == 0) {
|
||||
first = t;
|
||||
count++;
|
||||
}
|
||||
else if (count > 0) {
|
||||
if (buffer == null) {
|
||||
buffer = new SpinedBuffer<>();
|
||||
buffer.accept(first);
|
||||
count++;
|
||||
}
|
||||
|
||||
buffer.accept(t);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public StreamBuilder<T> add(T t) {
|
||||
accept(t);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<T> build() {
|
||||
int c = count;
|
||||
if (c >= 0) {
|
||||
// Switch count to negative value signalling the builder is built
|
||||
count = -count - 1;
|
||||
// Use this spliterator if 0 or 1 elements, otherwise use
|
||||
// the spliterator of the spined buffer
|
||||
return (c < 2) ? StreamSupport.stream(this) : StreamSupport.stream(buffer.spliterator());
|
||||
}
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// Spliterator implementation for 0 or 1 element
|
||||
// count == -1 for no elements
|
||||
// count == -2 for one element held by first
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super T> action) {
|
||||
if (count == -2) {
|
||||
action.accept(first);
|
||||
count = -1;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(Consumer<? super T> action) {
|
||||
if (count == -2) {
|
||||
action.accept(first);
|
||||
count = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final class IntStreamBuilderImpl
|
||||
extends AbstractStreamBuilderImpl<Integer, Spliterator.OfInt>
|
||||
implements StreamBuilder.OfInt, Spliterator.OfInt {
|
||||
// The first element in the stream
|
||||
// valid if count == 1
|
||||
int first;
|
||||
|
||||
// The first and subsequent elements in the stream
|
||||
// non-null if count == 2
|
||||
SpinedBuffer.OfInt buffer;
|
||||
|
||||
/**
|
||||
* Constructor for building a stream of 0 or more elements.
|
||||
*/
|
||||
IntStreamBuilderImpl() { }
|
||||
|
||||
/**
|
||||
* Constructor for a singleton stream.
|
||||
*
|
||||
* @param t the single element
|
||||
*/
|
||||
IntStreamBuilderImpl(int t) {
|
||||
first = t;
|
||||
count = -2;
|
||||
}
|
||||
|
||||
// StreamBuilder implementation
|
||||
|
||||
@Override
|
||||
public void accept(int t) {
|
||||
if (count == 0) {
|
||||
first = t;
|
||||
count++;
|
||||
}
|
||||
else if (count > 0) {
|
||||
if (buffer == null) {
|
||||
buffer = new SpinedBuffer.OfInt();
|
||||
buffer.accept(first);
|
||||
count++;
|
||||
}
|
||||
|
||||
buffer.accept(t);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntStream build() {
|
||||
int c = count;
|
||||
if (c >= 0) {
|
||||
// Switch count to negative value signalling the builder is built
|
||||
count = -count - 1;
|
||||
// Use this spliterator if 0 or 1 elements, otherwise use
|
||||
// the spliterator of the spined buffer
|
||||
return (c < 2) ? StreamSupport.intStream(this) : StreamSupport.intStream(buffer.spliterator());
|
||||
}
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// Spliterator implementation for 0 or 1 element
|
||||
// count == -1 for no elements
|
||||
// count == -2 for one element held by first
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(IntConsumer action) {
|
||||
if (count == -2) {
|
||||
action.accept(first);
|
||||
count = -1;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(IntConsumer action) {
|
||||
if (count == -2) {
|
||||
action.accept(first);
|
||||
count = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final class LongStreamBuilderImpl
|
||||
extends AbstractStreamBuilderImpl<Long, Spliterator.OfLong>
|
||||
implements StreamBuilder.OfLong, Spliterator.OfLong {
|
||||
// The first element in the stream
|
||||
// valid if count == 1
|
||||
long first;
|
||||
|
||||
// The first and subsequent elements in the stream
|
||||
// non-null if count == 2
|
||||
SpinedBuffer.OfLong buffer;
|
||||
|
||||
/**
|
||||
* Constructor for building a stream of 0 or more elements.
|
||||
*/
|
||||
LongStreamBuilderImpl() { }
|
||||
|
||||
/**
|
||||
* Constructor for a singleton stream.
|
||||
*
|
||||
* @param t the single element
|
||||
*/
|
||||
LongStreamBuilderImpl(long t) {
|
||||
first = t;
|
||||
count = -2;
|
||||
}
|
||||
|
||||
// StreamBuilder implementation
|
||||
|
||||
@Override
|
||||
public void accept(long t) {
|
||||
if (count == 0) {
|
||||
first = t;
|
||||
count++;
|
||||
}
|
||||
else if (count > 0) {
|
||||
if (buffer == null) {
|
||||
buffer = new SpinedBuffer.OfLong();
|
||||
buffer.accept(first);
|
||||
count++;
|
||||
}
|
||||
|
||||
buffer.accept(t);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LongStream build() {
|
||||
int c = count;
|
||||
if (c >= 0) {
|
||||
// Switch count to negative value signalling the builder is built
|
||||
count = -count - 1;
|
||||
// Use this spliterator if 0 or 1 elements, otherwise use
|
||||
// the spliterator of the spined buffer
|
||||
return (c < 2) ? StreamSupport.longStream(this) : StreamSupport.longStream(buffer.spliterator());
|
||||
}
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// Spliterator implementation for 0 or 1 element
|
||||
// count == -1 for no elements
|
||||
// count == -2 for one element held by first
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(LongConsumer action) {
|
||||
if (count == -2) {
|
||||
action.accept(first);
|
||||
count = -1;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(LongConsumer action) {
|
||||
if (count == -2) {
|
||||
action.accept(first);
|
||||
count = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final class DoubleStreamBuilderImpl
|
||||
extends AbstractStreamBuilderImpl<Double, Spliterator.OfDouble>
|
||||
implements StreamBuilder.OfDouble, Spliterator.OfDouble {
|
||||
// The first element in the stream
|
||||
// valid if count == 1
|
||||
double first;
|
||||
|
||||
// The first and subsequent elements in the stream
|
||||
// non-null if count == 2
|
||||
SpinedBuffer.OfDouble buffer;
|
||||
|
||||
/**
|
||||
* Constructor for building a stream of 0 or more elements.
|
||||
*/
|
||||
DoubleStreamBuilderImpl() { }
|
||||
|
||||
/**
|
||||
* Constructor for a singleton stream.
|
||||
*
|
||||
* @param t the single element
|
||||
*/
|
||||
DoubleStreamBuilderImpl(double t) {
|
||||
first = t;
|
||||
count = -2;
|
||||
}
|
||||
|
||||
// StreamBuilder implementation
|
||||
|
||||
@Override
|
||||
public void accept(double t) {
|
||||
if (count == 0) {
|
||||
first = t;
|
||||
count++;
|
||||
}
|
||||
else if (count > 0) {
|
||||
if (buffer == null) {
|
||||
buffer = new SpinedBuffer.OfDouble();
|
||||
buffer.accept(first);
|
||||
count++;
|
||||
}
|
||||
|
||||
buffer.accept(t);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoubleStream build() {
|
||||
int c = count;
|
||||
if (c >= 0) {
|
||||
// Switch count to negative value signalling the builder is built
|
||||
count = -count - 1;
|
||||
// Use this spliterator if 0 or 1 elements, otherwise use
|
||||
// the spliterator of the spined buffer
|
||||
return (c < 2) ? StreamSupport.doubleStream(this) : StreamSupport.doubleStream(buffer.spliterator());
|
||||
}
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// Spliterator implementation for 0 or 1 element
|
||||
// count == -1 for no elements
|
||||
// count == -2 for one element held by first
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(DoubleConsumer action) {
|
||||
if (count == -2) {
|
||||
action.accept(first);
|
||||
count = -1;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(DoubleConsumer action) {
|
||||
if (count == -2) {
|
||||
action.accept(first);
|
||||
count = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,19 +128,13 @@ public class AgentConfigurationError extends Error {
|
||||
public AgentConfigurationError(String error, String... params) {
|
||||
super();
|
||||
this.error = error;
|
||||
this.params = new String[params.length];
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
this.params[i] = params[i];
|
||||
}
|
||||
this.params = params.clone();
|
||||
}
|
||||
|
||||
public AgentConfigurationError(String error, Throwable cause, String... params) {
|
||||
super(cause);
|
||||
this.error = error;
|
||||
this.params = new String[params.length];
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
this.params[i] = params[i];
|
||||
}
|
||||
this.params = params.clone();
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
@ -148,7 +142,7 @@ public class AgentConfigurationError extends Error {
|
||||
}
|
||||
|
||||
public String[] getParams() {
|
||||
return params;
|
||||
return params.clone();
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1211605593516195475L;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
281
jdk/test/java/util/Arrays/SetAllTest.java
Normal file
281
jdk/test/java/util/Arrays/SetAllTest.java
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* @bug 8012650
|
||||
* @summary Unit test for setAll, parallelSetAll variants
|
||||
* @run testng SetAllTest
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.function.IntToDoubleFunction;
|
||||
import java.util.function.IntToLongFunction;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.assertSame;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
@Test
|
||||
public class SetAllTest {
|
||||
private static final IntFunction<String> toString = i -> "N" + Integer.valueOf(i);
|
||||
private static final IntFunction<String> fillString = i -> "X";
|
||||
private static final String[] r0 = {};
|
||||
private static final String[] r1 = { "N0" };
|
||||
private static final String[] r10 = { "N0", "N1", "N2", "N3", "N4", "N5", "N6", "N7", "N8", "N9" };
|
||||
|
||||
private Object[][] stringData = new Object[][] {
|
||||
{ "empty", 0, toString, r0 },
|
||||
{ "one", 1, toString, r1 },
|
||||
{ "ten", 10, toString, r10 },
|
||||
{ "fill", 3, fillString, new String[] { "X", "X", "X" }}
|
||||
};
|
||||
|
||||
private static final IntUnaryOperator toInt = i -> i << 1;
|
||||
private static final IntUnaryOperator fillInt = i -> 99;
|
||||
private static final int[] ir0 = {};
|
||||
private static final int[] ir1 = { 0 };
|
||||
private static final int[] ir10 = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 };
|
||||
private Object[][] intData = new Object[][] {
|
||||
{ "empty", 0, toInt, ir0 },
|
||||
{ "one", 1, toInt, ir1 },
|
||||
{ "ten", 10, toInt, ir10 },
|
||||
{ "fill", 3, fillInt, new int[] { 99, 99, 99 }}
|
||||
};
|
||||
|
||||
private static final IntToLongFunction toLong = i -> i << 1;
|
||||
private static final IntToLongFunction fillLong = i -> 9999L;
|
||||
private static final long[] lr0 = {};
|
||||
private static final long[] lr1 = { 0L };
|
||||
private static final long[] lr10 = { 0L, 2L, 4L, 6L, 8L, 10L, 12L, 14L, 16L, 18L };
|
||||
private Object[][] longData = new Object[][] {
|
||||
{ "empty", 0, toLong, lr0 },
|
||||
{ "one", 1, toLong, lr1 },
|
||||
{ "ten", 10, toLong, lr10 },
|
||||
{ "fill", 3, fillLong, new long[] { 9999L, 9999L, 9999L }}
|
||||
};
|
||||
|
||||
private static final IntToDoubleFunction toDouble = i -> i * 1.1;
|
||||
private static final IntToDoubleFunction fillDouble = i -> 3.14;
|
||||
private static final double[] dr0 = {};
|
||||
private static final double[] dr1 = { 0.0 };
|
||||
private static final double[] dr10 = { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };
|
||||
private Object[][] doubleData = new Object[][] {
|
||||
{ "empty", 0, toDouble, dr0 },
|
||||
{ "one", 1, toDouble, dr1 },
|
||||
{ "ten", 10, toDouble, dr10 },
|
||||
{ "fill", 3, fillDouble, new double[] { 3.14, 3.14, 3.14 }}
|
||||
};
|
||||
|
||||
@DataProvider(name="string")
|
||||
public Object[][] stringTests() { return stringData; }
|
||||
|
||||
@DataProvider(name="int")
|
||||
public Object[][] intTests() { return intData; }
|
||||
|
||||
@DataProvider(name="long")
|
||||
public Object[][] longTests() { return longData; }
|
||||
|
||||
@DataProvider(name="double")
|
||||
public Object[][] doubleTests() { return doubleData; }
|
||||
|
||||
@Test(dataProvider = "string")
|
||||
public void testSetAllString(String name, int size, IntFunction<String> generator, String[] expected) {
|
||||
String[] result = new String[size];
|
||||
Arrays.setAll(result, generator);
|
||||
assertEquals(result, expected, "setAll(String[], IntFunction<String>) case " + name + " failed.");
|
||||
|
||||
// ensure fresh array
|
||||
result = new String[size];
|
||||
Arrays.parallelSetAll(result, generator);
|
||||
assertEquals(result, expected, "parallelSetAll(String[], IntFunction<String>) case " + name + " failed.");
|
||||
}
|
||||
|
||||
@Test(dataProvider = "int")
|
||||
public void testSetAllInt(String name, int size, IntUnaryOperator generator, int[] expected) {
|
||||
int[] result = new int[size];
|
||||
Arrays.setAll(result, generator);
|
||||
assertEquals(result, expected, "setAll(int[], IntUnaryOperator) case " + name + " failed.");
|
||||
|
||||
// ensure fresh array
|
||||
result = new int[size];
|
||||
Arrays.parallelSetAll(result, generator);
|
||||
assertEquals(result, expected, "parallelSetAll(int[], IntUnaryOperator) case " + name + " failed.");
|
||||
}
|
||||
|
||||
@Test(dataProvider = "long")
|
||||
public void testSetAllLong(String name, int size, IntToLongFunction generator, long[] expected) {
|
||||
long[] result = new long[size];
|
||||
Arrays.setAll(result, generator);
|
||||
assertEquals(result, expected, "setAll(long[], IntToLongFunction) case " + name + " failed.");
|
||||
|
||||
// ensure fresh array
|
||||
result = new long[size];
|
||||
Arrays.parallelSetAll(result, generator);
|
||||
assertEquals(result, expected, "parallelSetAll(long[], IntToLongFunction) case " + name + " failed.");
|
||||
}
|
||||
|
||||
private void assertDoubleArrayEquals(double[] actual, double[] expected, double delta, String msg) {
|
||||
if (actual.length != expected.length) {
|
||||
fail(msg + ": length mismatch, expected " + expected.length + ", got " + actual.length);
|
||||
}
|
||||
|
||||
for (int i = 0; i < actual.length; i++) {
|
||||
assertEquals(actual[i], expected[i], delta, msg + "(mismatch at index " + i + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "double")
|
||||
public void testSetAllDouble(String name, int size, IntToDoubleFunction generator, double[] expected) {
|
||||
double[] result = new double[size];
|
||||
Arrays.setAll(result, generator);
|
||||
assertDoubleArrayEquals(result, expected, 0.05, "setAll(double[], IntToDoubleFunction) case " + name + " failed.");
|
||||
|
||||
// ensure fresh array
|
||||
result = new double[size];
|
||||
Arrays.parallelSetAll(result, generator);
|
||||
assertDoubleArrayEquals(result, expected, 0.05, "setAll(double[], IntToDoubleFunction) case " + name + " failed.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringSetNulls() {
|
||||
String[] ar = new String[2];
|
||||
try {
|
||||
Arrays.setAll(null, i -> "X");
|
||||
fail("Arrays.setAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(null, i -> "X");
|
||||
fail("Arrays.parallelSetAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.setAll(ar, null);
|
||||
fail("Arrays.setAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(ar, null);
|
||||
fail("Arrays.parallelSetAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntSetNulls() {
|
||||
int[] ar = new int[2];
|
||||
try {
|
||||
Arrays.setAll(null, (IntUnaryOperator) i -> i);
|
||||
fail("Arrays.setAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(null, (IntUnaryOperator) i -> i);
|
||||
fail("Arrays.parallelSetAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.setAll(ar, null);
|
||||
fail("Arrays.setAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(ar, null);
|
||||
fail("Arrays.parallelSetAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongSetNulls() {
|
||||
long[] ar = new long[2];
|
||||
try {
|
||||
Arrays.setAll(null, (IntToLongFunction) i -> Long.MAX_VALUE);
|
||||
fail("Arrays.setAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(null, (IntToLongFunction) i -> Long.MAX_VALUE);
|
||||
fail("Arrays.parallelSetAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.setAll(ar, null);
|
||||
fail("Arrays.setAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(ar, null);
|
||||
fail("Arrays.parallelSetAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubleSetNulls() {
|
||||
double[] ar = new double[2];
|
||||
try {
|
||||
Arrays.setAll(null, (IntToDoubleFunction) i -> Math.E);
|
||||
fail("Arrays.setAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(null, (IntToDoubleFunction) i -> Math.E);
|
||||
fail("Arrays.parallelSetAll(null, foo) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.setAll(ar, null);
|
||||
fail("Arrays.setAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
Arrays.parallelSetAll(ar, null);
|
||||
fail("Arrays.parallelSetAll(array, null) should throw NPE");
|
||||
} catch (NullPointerException npe) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user