diff --git a/jdk/src/share/classes/java/net/Inet6Address.java b/jdk/src/share/classes/java/net/Inet6Address.java
index a2e66f09b70..4a2d4e22473 100644
--- a/jdk/src/share/classes/java/net/Inet6Address.java
+++ b/jdk/src/share/classes/java/net/Inet6Address.java
@@ -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();
}
}
diff --git a/jdk/src/share/classes/java/sql/Driver.java b/jdk/src/share/classes/java/sql/Driver.java
index 1682b75c910..27ad3e0407d 100644
--- a/jdk/src/share/classes/java/sql/Driver.java
+++ b/jdk/src/share/classes/java/sql/Driver.java
@@ -44,13 +44,16 @@ import java.util.logging.Logger;
*
*
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
- *
- * Class.forName("foo.bah.Driver")
- *
- *
+ * user can load and register a driver by calling:
+ *
+ * {@code Class.forName("foo.bah.Driver")}
+ *
+ * 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 {
diff --git a/jdk/src/share/classes/java/sql/DriverAction.java b/jdk/src/share/classes/java/sql/DriverAction.java
new file mode 100644
index 00000000000..167168c9b85
--- /dev/null
+++ b/jdk/src/share/classes/java/sql/DriverAction.java
@@ -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}.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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();
+
+}
diff --git a/jdk/src/share/classes/java/sql/DriverManager.java b/jdk/src/share/classes/java/sql/DriverManager.java
index b0d8decf40b..fbe16363529 100644
--- a/jdk/src/share/classes/java/sql/DriverManager.java
+++ b/jdk/src/share/classes/java/sql/DriverManager.java
@@ -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 DriverManager.
+ * Registers the given driver with the {@code DriverManager}.
* A newly-loaded driver class should call
- * the method registerDriver to make itself
- * known to the DriverManager.
+ * 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
- * DriverManager
+ * {@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 DriverManager's list.
- * Applets can only deregister drivers from their own classloaders.
+ * Removes the specified driver from the {@code DriverManager}'s list of
+ * registered drivers.
+ *
+ * If a {@code null} value is specified for the driver to be removed, then no
+ * action is taken.
+ *
+ * If a security manager exists and its {@code checkPermission} denies
+ * permission, then a {@code SecurityException} will be thrown.
+ *
+ * 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.
+ *
+ * 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;
+ }
}
diff --git a/jdk/src/share/classes/java/sql/SQLPermission.java b/jdk/src/share/classes/java/sql/SQLPermission.java
index e2207db3262..3aa5a42860b 100644
--- a/jdk/src/share/classes/java/sql/SQLPermission.java
+++ b/jdk/src/share/classes/java/sql/SQLPermission.java
@@ -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 SecurityManager will check
- * when code that is running in an applet, or an application with a
+ * when code that is running an application with a
* SecurityManager enabled, calls the
+ * {@code DriverManager.deregisterDriver} method,
* DriverManager.setLogWriter method,
* DriverManager.setLogStream (deprecated) method,
* {@code SyncFactory.setJNDIContext} method,
@@ -95,14 +96,16 @@ import java.security.*;
* Connection or
* objects created from the Connection
* will wait for the database to reply to any one request.
+ *
+ * | deregisterDriver |
+ * Allows the invocation of the {@code DriverManager}
+ * method {@code deregisterDriver} |
+ * Permits an application to remove a JDBC driver from the list of
+ * registered Drivers and release its resources. |
+ *
*
*
*
- * The person running an applet decides what permissions to allow
- * and will run the Policy Tool to create an
- * SQLPermission in a policy file. A programmer does
- * not use a constructor directly to create an instance of SQLPermission
- * but rather uses a tool.
* @since 1.3
* @see java.security.BasicPermission
* @see java.security.Permission
diff --git a/jdk/src/share/classes/java/util/Arrays.java b/jdk/src/share/classes/java/util/Arrays.java
index e513398683b..af0663bff1a 100644
--- a/jdk/src/share/classes/java/util/Arrays.java
+++ b/jdk/src/share/classes/java/util/Arrays.java
@@ -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.
+ *
+ *
If the generator function throws an exception, it is relayed to
+ * the caller and the array is left in an indeterminate state.
+ *
+ * @param 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 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.
+ *
+ * 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 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 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.
+ *
+ * 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.
+ *
+ *
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.
+ *
+ *
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.
+ *
+ *
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.
+ *
+ *
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.
+ *
+ *
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.
*
*
The spliterator reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#IMMUTABLE}.
*
- * @param 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 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 Spliterator 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.
*
* The spliterator reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#IMMUTABLE}.
*
- * @param 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 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 Spliterator spliterator(T[] array, int fromIndex, int toIndex) {
- return Spliterators.spliterator(array, fromIndex, toIndex,
+ public static Spliterator 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.
*
* 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.
*
*
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.
*
*
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.
*
*
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.
*
*
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.
*
*
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 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 Stream 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 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 Stream 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));
+ }
}
diff --git a/jdk/src/share/classes/java/util/stream/Collectors.java b/jdk/src/share/classes/java/util/stream/Collectors.java
new file mode 100644
index 00000000000..0d14c888e9e
--- /dev/null
+++ b/jdk/src/share/classes/java/util/stream/Collectors.java
@@ -0,0 +1,1320 @@
+/*
+ * 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.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Comparators;
+import java.util.DoubleSummaryStatistics;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IntSummaryStatistics;
+import java.util.Iterator;
+import java.util.List;
+import java.util.LongSummaryStatistics;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Set;
+import java.util.StringJoiner;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.BiFunction;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.function.ToDoubleFunction;
+import java.util.function.ToIntFunction;
+import java.util.function.ToLongFunction;
+
+/**
+ * Implementations of {@link Collector} that implement various useful reduction
+ * operations, such as accumulating elements into collections, summarizing
+ * elements according to various criteria, etc.
+ *
+ * The following are examples of using the predefined {@code Collector}
+ * implementations in {@link Collectors} with the {@code Stream} API to perform
+ * mutable reduction tasks:
+ *
+ *
{@code
+ * // Accumulate elements into a List
+ * List list = people.collect(Collectors.toList());
+ *
+ * // Accumulate elements into a TreeSet
+ * List list = people.collect(Collectors.toCollection(TreeSet::new));
+ *
+ * // Convert elements to strings and concatenate them, separated by commas
+ * String joined = stream.map(Object::toString)
+ * .collect(Collectors.toStringJoiner(", "))
+ * .toString();
+ *
+ * // Find highest-paid employee
+ * Employee highestPaid = employees.stream()
+ * .collect(Collectors.maxBy(Comparators.comparing(Employee::getSalary)));
+ *
+ * // Group employees by department
+ * Map> byDept
+ * = employees.stream()
+ * .collect(Collectors.groupingBy(Employee::getDepartment));
+ *
+ * // Find highest-paid employee by department
+ * Map highestPaidByDept
+ * = employees.stream()
+ * .collect(Collectors.groupingBy(Employee::getDepartment,
+ * Collectors.maxBy(Comparators.comparing(Employee::getSalary))));
+ *
+ * // Partition students into passing and failing
+ * Map> passingFailing =
+ * students.stream()
+ * .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD);
+ *
+ * }
+ *
+ * TODO explanation of parallel collection
+ *
+ * @since 1.8
+ */
+public final class Collectors {
+
+ private static final Set CH_CONCURRENT
+ = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
+ Collector.Characteristics.STRICTLY_MUTATIVE,
+ Collector.Characteristics.UNORDERED));
+ private static final Set CH_STRICT
+ = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.STRICTLY_MUTATIVE));
+ private static final Set CH_STRICT_UNORDERED
+ = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.STRICTLY_MUTATIVE,
+ Collector.Characteristics.UNORDERED));
+
+ private Collectors() { }
+
+ /**
+ * Returns a merge function, suitable for use in
+ * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or
+ * {@link #toMap(Function, Function, BinaryOperator) toMap()}, which always
+ * throws {@code IllegalStateException}. This can be used to enforce the
+ * assumption that the elements being collected are distinct.
+ *
+ * @param the type of input arguments to the merge function
+ * @return a merge function which always throw {@code IllegalStateException}
+ *
+ * @see #firstWinsMerger()
+ * @see #lastWinsMerger()
+ */
+ public static BinaryOperator throwingMerger() {
+ return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
+ }
+
+ /**
+ * Returns a merge function, suitable for use in
+ * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or
+ * {@link #toMap(Function, Function, BinaryOperator) toMap()},
+ * which implements a "first wins" policy.
+ *
+ * @param the type of input arguments to the merge function
+ * @return a merge function which always returns its first argument
+ * @see #lastWinsMerger()
+ * @see #throwingMerger()
+ */
+ public static BinaryOperator firstWinsMerger() {
+ return (u,v) -> u;
+ }
+
+ /**
+ * Returns a merge function, suitable for use in
+ * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or
+ * {@link #toMap(Function, Function, BinaryOperator) toMap()},
+ * which implements a "last wins" policy.
+ *
+ * @param the type of input arguments to the merge function
+ * @return a merge function which always returns its second argument
+ * @see #firstWinsMerger()
+ * @see #throwingMerger()
+ */
+ public static BinaryOperator lastWinsMerger() {
+ return (u,v) -> v;
+ }
+
+ /**
+ * Simple implementation class for {@code Collector}.
+ *
+ * @param the type of elements to be collected
+ * @param the type of the result
+ */
+ private static final class CollectorImpl implements Collector {
+ private final Supplier resultSupplier;
+ private final BiFunction accumulator;
+ private final BinaryOperator combiner;
+ private final Set characteristics;
+
+ CollectorImpl(Supplier resultSupplier,
+ BiFunction accumulator,
+ BinaryOperator combiner,
+ Set characteristics) {
+ this.resultSupplier = resultSupplier;
+ this.accumulator = accumulator;
+ this.combiner = combiner;
+ this.characteristics = characteristics;
+ }
+
+ CollectorImpl(Supplier resultSupplier,
+ BiFunction accumulator,
+ BinaryOperator combiner) {
+ this(resultSupplier, accumulator, combiner, Collections.emptySet());
+ }
+
+ @Override
+ public BiFunction accumulator() {
+ return accumulator;
+ }
+
+ @Override
+ public Supplier resultSupplier() {
+ return resultSupplier;
+ }
+
+ @Override
+ public BinaryOperator combiner() {
+ return combiner;
+ }
+
+ @Override
+ public Set characteristics() {
+ return characteristics;
+ }
+ }
+
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into a
+ * new {@code Collection}, in encounter order. The {@code Collection} is
+ * created by the provided factory.
+ *
+ * @param the type of the input elements
+ * @param the type of the resulting {@code Collection}
+ * @param collectionFactory a {@code Supplier} which returns a new, empty
+ * {@code Collection} of the appropriate type
+ * @return a {@code Collector} which collects all the input elements into a
+ * {@code Collection}, in encounter order
+ */
+ public static >
+ Collector toCollection(Supplier collectionFactory) {
+ return new CollectorImpl<>(collectionFactory,
+ (r, t) -> { r.add(t); return r; },
+ (r1, r2) -> { r1.addAll(r2); return r1; },
+ CH_STRICT);
+ }
+
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into a
+ * new {@code List}. There are no guarantees on the type, mutability,
+ * serializability, or thread-safety of the {@code List} returned.
+ *
+ * @param the type of the input elements
+ * @return a {@code Collector} which collects all the input elements into a
+ * {@code List}, in encounter order
+ */
+ public static
+ Collector> toList() {
+ BiFunction, T, List> accumulator = (list, t) -> {
+ switch (list.size()) {
+ case 0:
+ return Collections.singletonList(t);
+ case 1:
+ List newList = new ArrayList<>();
+ newList.add(list.get(0));
+ newList.add(t);
+ return newList;
+ default:
+ list.add(t);
+ return list;
+ }
+ };
+ BinaryOperator> combiner = (left, right) -> {
+ switch (left.size()) {
+ case 0:
+ return right;
+ case 1:
+ List newList = new ArrayList<>(left.size() + right.size());
+ newList.addAll(left);
+ newList.addAll(right);
+ return newList;
+ default:
+ left.addAll(right);
+ return left;
+ }
+ };
+ return new CollectorImpl<>(Collections::emptyList, accumulator, combiner);
+ }
+
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into a
+ * new {@code Set}. There are no guarantees on the type, mutability,
+ * serializability, or thread-safety of the {@code Set} returned.
+ *
+ * This is an {@link Collector.Characteristics#UNORDERED unordered}
+ * Collector.
+ *
+ * @param the type of the input elements
+ * @return a {@code Collector} which collects all the input elements into a
+ * {@code Set}
+ */
+ public static
+ Collector> toSet() {
+ return new CollectorImpl<>((Supplier>) HashSet::new,
+ (r, t) -> { r.add(t); return r; },
+ (r1, r2) -> { r1.addAll(r2); return r1; },
+ CH_STRICT_UNORDERED);
+ }
+
+ /**
+ * Returns a {@code Collector} that concatenates the input elements into a
+ * new {@link StringBuilder}.
+ *
+ * @return a {@code Collector} which collects String elements into a
+ * {@code StringBuilder}, in encounter order
+ */
+ public static Collector toStringBuilder() {
+ return new CollectorImpl<>(StringBuilder::new,
+ (r, t) -> { r.append(t); return r; },
+ (r1, r2) -> { r1.append(r2); return r1; },
+ CH_STRICT);
+ }
+
+ /**
+ * Returns a {@code Collector} that concatenates the input elements into a
+ * new {@link StringJoiner}, using the specified delimiter.
+ *
+ * @param delimiter the delimiter to be used between each element
+ * @return A {@code Collector} which collects String elements into a
+ * {@code StringJoiner}, in encounter order
+ */
+ public static Collector toStringJoiner(CharSequence delimiter) {
+ BinaryOperator merger = (sj, other) -> {
+ if (other.length() > 0)
+ sj.add(other.toString());
+ return sj;
+ };
+ return new CollectorImpl<>(() -> new StringJoiner(delimiter),
+ (r, t) -> { r.add(t); return r; },
+ merger, CH_STRICT);
+ }
+
+ /**
+ * {@code BinaryOperator