OpenJDK / bsd-port / jdk9 / jdk
changeset 7826:23e68a8e4b91
Merge
author | lana |
---|---|
date | Wed, 07 Aug 2013 19:56:20 -0700 |
parents | e193c4ad940a 8c50c27418d3 |
children | e0f6039c0290 |
files | test/java/lang/System/MacJNUEncoding/ExpectedEncoding.java test/java/lang/System/MacJNUEncoding/MacJNUEncoding.sh |
diffstat | 182 files changed, 5611 insertions(+), 2734 deletions(-) [+] |
line wrap: on
line diff
--- a/src/macosx/native/java/util/SCDynamicStoreConfig.m Wed Aug 07 19:52:47 2013 -0700 +++ b/src/macosx/native/java/util/SCDynamicStoreConfig.m Wed Aug 07 19:56:20 2013 -0700 @@ -103,7 +103,6 @@ CFTypeRef realmInfo = SCDynamicStoreCopyValue(store, (CFStringRef) [NSString stringWithFormat:@"Kerberos:%@", realm]); if (CFGetTypeID(realmInfo) != CFDictionaryGetTypeID()) { - NSLog(@"Unexpected CFType for realm Info: %lu", CFGetTypeID(realmInfo)); return nil; } @@ -140,7 +139,6 @@ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("java"), _SCDynamicStoreCallBack, NULL); if (store == NULL) { - NSLog(@"Unable to load SCDynamicStore to install NotificationCallback"); return; } @@ -171,19 +169,11 @@ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("java-kerberos"), NULL, NULL); if (store == NULL) { - NSLog(@"Unable to load SCDynamicStore"); - return NULL; - } - - // Create the store if it is NULL and set it. - if (store == NULL) { - NSLog(@"Invalid value for SCDynamicStore"); return NULL; } CFTypeRef realms = SCDynamicStoreCopyValue(store, (CFStringRef) KERBEROS_DEFAULT_REALMS); if (realms == NULL || CFGetTypeID(realms) != CFArrayGetTypeID()) { - NSLog(@"Unable to load realm info from SCDynamicStore"); if (realms) CFRelease(realms); CFRelease(store); return NULL; @@ -192,7 +182,6 @@ CFTypeRef realmMappings = SCDynamicStoreCopyValue(store, (CFStringRef) KERBEROS_DEFAULT_REALM_MAPPINGS); if (realmMappings == NULL || CFGetTypeID(realmMappings) != CFArrayGetTypeID()) { - NSLog(@"Unable to load realm mapping info from SCDynamicStore"); if (realmMappings) CFRelease(realmMappings); CFRelease(realms); CFRelease(store);
--- a/src/share/classes/com/sun/security/auth/PolicyFile.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/com/sun/security/auth/PolicyFile.java Wed Aug 07 19:56:20 2013 -0700 @@ -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 @@ -47,6 +47,10 @@ import sun.security.util.PropertyExpander; +import sun.security.provider.PolicyParser.PrincipalEntry; +import sun.security.provider.PolicyParser.GrantEntry; +import sun.security.provider.PolicyParser.PermissionEntry; + /** * This class represents a default implementation for * <code>javax.security.auth.Policy</code>. @@ -469,7 +473,8 @@ * @param policyFile the policy Reader object. */ private void init(URL policy) { - PolicyParser pp = new PolicyParser(expandProperties); + sun.security.provider.PolicyParser pp = + new sun.security.provider.PolicyParser(expandProperties); try { InputStreamReader isr = new InputStreamReader(getInputStream(policy)); @@ -477,12 +482,12 @@ isr.close(); KeyStore keyStore = initKeyStore(policy, pp.getKeyStoreUrl(), pp.getKeyStoreType()); - Enumeration<PolicyParser.GrantEntry> enum_ = pp.grantElements(); + Enumeration<GrantEntry> enum_ = pp.grantElements(); while (enum_.hasMoreElements()) { - PolicyParser.GrantEntry ge = enum_.nextElement(); + GrantEntry ge = enum_.nextElement(); addGrantEntry(ge, keyStore); } - } catch (PolicyParser.ParsingException pe) { + } catch (sun.security.provider.PolicyParser.ParsingException pe) { System.err.println(AUTH_POLICY + rb.getString(".error.parsing.") + policy); System.err.println(AUTH_POLICY + @@ -521,8 +526,8 @@ * * @return null if signedBy alias is not recognized */ - CodeSource getCodeSource(PolicyParser.GrantEntry ge, KeyStore keyStore) - throws java.net.MalformedURLException + CodeSource getCodeSource(GrantEntry ge, KeyStore keyStore) + throws java.net.MalformedURLException { Certificate[] certs = null; if (ge.signedBy != null) { @@ -559,20 +564,18 @@ /** * Add one policy entry to the vector. */ - private void addGrantEntry(PolicyParser.GrantEntry ge, - KeyStore keyStore) { + private void addGrantEntry(GrantEntry ge, KeyStore keyStore) { if (debug != null) { debug.println("Adding policy entry: "); debug.println(" signedBy " + ge.signedBy); debug.println(" codeBase " + ge.codeBase); if (ge.principals != null && ge.principals.size() > 0) { - ListIterator<PolicyParser.PrincipalEntry> li = - ge.principals.listIterator(); + ListIterator<PrincipalEntry> li = ge.principals.listIterator(); while (li.hasNext()) { - PolicyParser.PrincipalEntry pppe = li.next(); - debug.println(" " + pppe.principalClass + - " " + pppe.principalName); + PrincipalEntry pppe = li.next(); + debug.println(" " + pppe.getPrincipalClass() + + " " + pppe.getPrincipalName()); } } debug.println(); @@ -584,10 +587,9 @@ if (codesource == null) return; PolicyEntry entry = new PolicyEntry(codesource); - Enumeration<PolicyParser.PermissionEntry> enum_ = - ge.permissionElements(); + Enumeration<PermissionEntry> enum_ = ge.permissionElements(); while (enum_.hasMoreElements()) { - PolicyParser.PermissionEntry pe = enum_.nextElement(); + PermissionEntry pe = enum_.nextElement(); try { // XXX special case PrivateCredentialPermission-SELF Permission perm; @@ -998,11 +1000,11 @@ return true; } - ListIterator<PolicyParser.PrincipalEntry> pli = - scs.getPrincipals().listIterator(); + ListIterator<PrincipalEntry> pli = + scs.getPrincipals().listIterator(); while (pli.hasNext()) { - PolicyParser.PrincipalEntry principal = pli.next(); + PrincipalEntry principal = pli.next(); // XXX // if the Policy entry's Principal does not contain a @@ -1050,30 +1052,29 @@ * if (y == 1), it's the principal name. */ private String[][] getPrincipalInfo - (PolicyParser.PrincipalEntry principal, - final CodeSource accCs) { + (PrincipalEntry principal, final CodeSource accCs) { // there are 3 possibilities: // 1) the entry's Principal class and name are not wildcarded // 2) the entry's Principal name is wildcarded only // 3) the entry's Principal class and name are wildcarded - if (!principal.principalClass.equals - (PolicyParser.PrincipalEntry.WILDCARD_CLASS) && - !principal.principalName.equals - (PolicyParser.PrincipalEntry.WILDCARD_NAME)) { + if (!principal.getPrincipalClass().equals + (PrincipalEntry.WILDCARD_CLASS) && + !principal.getPrincipalName().equals + (PrincipalEntry.WILDCARD_NAME)) { // build a PrivateCredentialPermission for the principal // from the Policy entry String[][] info = new String[1][2]; - info[0][0] = principal.principalClass; - info[0][1] = principal.principalName; + info[0][0] = principal.getPrincipalClass(); + info[0][1] = principal.getPrincipalName(); return info; - } else if (!principal.principalClass.equals - (PolicyParser.PrincipalEntry.WILDCARD_CLASS) && - principal.principalName.equals - (PolicyParser.PrincipalEntry.WILDCARD_NAME)) { + } else if (!principal.getPrincipalClass().equals + (PrincipalEntry.WILDCARD_CLASS) && + principal.getPrincipalName().equals + (PrincipalEntry.WILDCARD_NAME)) { // build a PrivateCredentialPermission for all // the Subject's principals that are instances of principalClass @@ -1088,7 +1089,7 @@ // If it doesn't, we should stop here with a ClassCastException. @SuppressWarnings("unchecked") Class<? extends Principal> pClass = (Class<? extends Principal>) - Class.forName(principal.principalClass, false, + Class.forName(principal.getPrincipalClass(), false, ClassLoader.getSystemClassLoader()); principalSet = scs.getSubject().getPrincipals(pClass); } catch (Exception e) { @@ -1387,6 +1388,7 @@ } } +@SuppressWarnings("deprecation") class PolicyPermissions extends PermissionCollection { private static final long serialVersionUID = -1954188373270545523L;
--- a/src/share/classes/com/sun/security/auth/SubjectCodeSource.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/com/sun/security/auth/SubjectCodeSource.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, 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 @@ -33,6 +33,7 @@ import java.lang.reflect.Constructor; import javax.security.auth.Subject; +import sun.security.provider.PolicyParser.PrincipalEntry; /** * <p> This <code>SubjectCodeSource</code> class contains @@ -57,7 +58,7 @@ }); private Subject subject; - private LinkedList<PolicyParser.PrincipalEntry> principals; + private LinkedList<PrincipalEntry> principals; private static final Class[] PARAMS = { String.class }; private static final sun.security.util.Debug debug = sun.security.util.Debug.getInstance("auth", "\t[Auth Access]"); @@ -87,14 +88,14 @@ * <code>SubjectCodeSource</code> <p> */ SubjectCodeSource(Subject subject, - LinkedList<PolicyParser.PrincipalEntry> principals, + LinkedList<PrincipalEntry> principals, URL url, Certificate[] certs) { super(url, certs); this.subject = subject; this.principals = (principals == null ? - new LinkedList<PolicyParser.PrincipalEntry>() : - new LinkedList<PolicyParser.PrincipalEntry>(principals)); + new LinkedList<PrincipalEntry>() : + new LinkedList<PrincipalEntry>(principals)); sysClassLoader = java.security.AccessController.doPrivileged (new java.security.PrivilegedAction<ClassLoader>() { public ClassLoader run() { @@ -114,7 +115,7 @@ * <code>SubjectCodeSource</code> as a <code>LinkedList</code> * of <code>PolicyParser.PrincipalEntry</code> objects. */ - LinkedList<PolicyParser.PrincipalEntry> getPrincipals() { + LinkedList<PrincipalEntry> getPrincipals() { return principals; } @@ -167,7 +168,7 @@ */ public boolean implies(CodeSource codesource) { - LinkedList<PolicyParser.PrincipalEntry> subjectList = null; + LinkedList<PrincipalEntry> subjectList = null; if (codesource == null || !(codesource instanceof SubjectCodeSource) || @@ -197,20 +198,19 @@ return false; } - ListIterator<PolicyParser.PrincipalEntry> li = - this.principals.listIterator(0); + ListIterator<PrincipalEntry> li = this.principals.listIterator(0); while (li.hasNext()) { - PolicyParser.PrincipalEntry pppe = li.next(); + PrincipalEntry pppe = li.next(); try { // handle PrincipalComparators Class<?> principalComparator = Class.forName( - pppe.principalClass, true, sysClassLoader); + pppe.getPrincipalClass(), true, sysClassLoader); Constructor<?> c = principalComparator.getConstructor(PARAMS); PrincipalComparator pc = (PrincipalComparator)c.newInstance - (new Object[] { pppe.principalName }); + (new Object[] { pppe.getPrincipalName() }); if (!pc.implies(that.getSubject())) { if (debug != null) @@ -236,11 +236,10 @@ Iterator<Principal> i = that.getSubject().getPrincipals().iterator(); - subjectList = new LinkedList<PolicyParser.PrincipalEntry>(); + subjectList = new LinkedList<PrincipalEntry>(); while (i.hasNext()) { Principal p = i.next(); - PolicyParser.PrincipalEntry spppe = - new PolicyParser.PrincipalEntry + PrincipalEntry spppe = new PrincipalEntry (p.getClass().getName(), p.getName()); subjectList.add(spppe); } @@ -281,23 +280,19 @@ * <i>pppe</i> argument. */ private boolean subjectListImpliesPrincipalEntry( - LinkedList<PolicyParser.PrincipalEntry> subjectList, - PolicyParser.PrincipalEntry pppe) { + LinkedList<PrincipalEntry> subjectList, PrincipalEntry pppe) { - ListIterator<PolicyParser.PrincipalEntry> li = - subjectList.listIterator(0); + ListIterator<PrincipalEntry> li = subjectList.listIterator(0); while (li.hasNext()) { - PolicyParser.PrincipalEntry listPppe = li.next(); + PrincipalEntry listPppe = li.next(); - if (pppe.principalClass.equals - (PolicyParser.PrincipalEntry.WILDCARD_CLASS) || - pppe.principalClass.equals - (listPppe.principalClass)) { - - if (pppe.principalName.equals - (PolicyParser.PrincipalEntry.WILDCARD_NAME) || - pppe.principalName.equals - (listPppe.principalName)) + if (pppe.getPrincipalClass().equals + (PrincipalEntry.WILDCARD_CLASS) || + pppe.getPrincipalClass().equals(listPppe.getPrincipalClass())) + { + if (pppe.getPrincipalName().equals + (PrincipalEntry.WILDCARD_NAME) || + pppe.getPrincipalName().equals(listPppe.getPrincipalName())) return true; } } @@ -390,13 +385,12 @@ } } if (principals != null) { - ListIterator<PolicyParser.PrincipalEntry> li = - principals.listIterator(); + ListIterator<PrincipalEntry> li = principals.listIterator(); while (li.hasNext()) { - PolicyParser.PrincipalEntry pppe = li.next(); + PrincipalEntry pppe = li.next(); returnMe = returnMe + rb.getString("NEWLINE") + - pppe.principalClass + " " + - pppe.principalName; + pppe.getPrincipalClass() + " " + + pppe.getPrincipalName(); } } return returnMe;
--- a/src/share/classes/com/sun/tools/hat/resources/hat.js Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/com/sun/tools/hat/resources/hat.js Wed Aug 07 19:56:20 2013 -0700 @@ -151,7 +151,7 @@ while (tmp != null) { res[res.length] = tmp; tmp = tmp.superclass; - } + } return res; } @@ -263,16 +263,19 @@ if (name == 'class') { return wrapJavaValue(instance.clazz); - } else if (name == 'toString') { - return function() { - return instance.toString(); - } } else if (name == 'wrapped-object') { return instance; } return undefined; - } + }, + __call__: function(name) { + if (name == 'toString') { + return instance.toString(); + } else { + return undefined; + } + } } } @@ -297,7 +300,7 @@ return true; } } - return theJavaClassProto[name] != undefined; + return false; }, __get__ : function(name) { for (var i in fields) { @@ -305,7 +308,7 @@ return wrapJavaValue(fields[i].value); } } - return theJavaClassProto[name]; + return undefined; } } @@ -322,7 +325,12 @@ this.name = jclass.name; this.fields = jclass.fields; this['wrapped-object'] = jclass; - this.__proto__ = this.statics; + } + + for (var i in theJavaClassProto) { + if (typeof theJavaClassProto[i] == 'function') { + JavaClassWrapper.prototype[i] = theJavaClassProto[i]; + } } // returns wrapper for Java object arrays @@ -334,32 +342,35 @@ __getIds__ : function() { var res = new Array(elements.length); for (var i = 0; i < elements.length; i++) { - res[i] = i; + res[i] = String(i); } return res; }, __has__: function(name) { - return (typeof(name) == 'number' && - name >= 0 && name < elements.length) || + return (name >= 0 && name < elements.length) || name == 'length' || name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__ : function(name) { - if (typeof(name) == 'number' && - name >= 0 && name < elements.length) { + if (name >= 0 && name < elements.length) { return wrapJavaValue(elements[name]); } else if (name == 'length') { return elements.length; } else if (name == 'class') { return wrapJavaValue(array.clazz); - } else if (name == 'toString') { - return function() { return array.toString(); } } else if (name == 'wrapped-object') { return array; } else { return undefined; } - } + }, + __call__: function(name) { + if (name == 'toString') { + return array.toString(); + } else { + return undefined; + } + } } } @@ -373,26 +384,22 @@ __getIds__ : function() { var r = new Array(array.length); for (var i = 0; i < array.length; i++) { - r[i] = i; + r[i] = String(i); } return r; }, __has__: function(name) { - return (typeof(name) == 'number' && - name >= 0 && name < array.length) || + return (name >= 0 && name < array.length) || name == 'length' || name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__: function(name) { - if (typeof(name) == 'number' && - name >= 0 && name < array.length) { + if (name >= 0 && name < array.length) { return elements[name]; } if (name == 'length') { return array.length; - } else if (name == 'toString') { - return function() { return array.valueString(true); } } else if (name == 'wrapped-object') { return array; } else if (name == 'class') { @@ -400,7 +407,14 @@ } else { return undefined; } - } + }, + __call__: function(name) { + if (name == 'toString') { + return array.valueString(true); + } else { + return undefined; + } + } } } return javaObject(thing); @@ -673,34 +687,33 @@ __getIds__ : function() { var res = new Array(path.length); for (var i = 0; i < path.length; i++) { - res[i] = i; + res[i] = String(i); } return res; }, __has__ : function (name) { - return (typeof(name) == 'number' && - name >= 0 && name < path.length) || + return (name >= 0 && name < path.length) || name == 'length' || name == 'toHtml' || name == 'toString'; }, __get__ : function(name) { - if (typeof(name) == 'number' && - name >= 0 && name < path.length) { + if (name >= 0 && name < path.length) { return path[name]; } else if (name == 'length') { return path.length; - } else if (name == 'toHtml') { - return function() { - return computeDescription(true); - } - } else if (name == 'toString') { - return function() { - return computeDescription(false); - } } else { return undefined; } }, + __call__: function(name) { + if (name == 'toHtml') { + return computeDescription(true); + } else if (name == 'toString') { + return computeDescription(false); + } else { + return undefined; + } + } }; } @@ -1005,22 +1018,8 @@ return "<a href='/object/" + id + "'>" + name + "@" + id + "</a>"; } - } else if ((typeof(obj) == 'object') || (obj instanceof JSAdapter)) { - if (obj instanceof java.lang.Object) { - // script wrapped Java object - obj = wrapIterator(obj); - // special case for enumeration - if (obj instanceof java.util.Enumeration) { - var res = "[ "; - while (obj.hasMoreElements()) { - res += toHtml(obj.nextElement()) + ", "; - } - res += "]"; - return res; - } else { - return obj; - } - } else if (obj instanceof Array) { + } else if (obj instanceof Object) { + if (Array.isArray(obj)) { // script array var res = "[ "; for (var i in obj) { @@ -1047,8 +1046,19 @@ } } } else { - // JavaScript primitive value - return obj; + // a Java object + obj = wrapIterator(obj); + // special case for enumeration + if (obj instanceof java.util.Enumeration) { + var res = "[ "; + while (obj.hasMoreElements()) { + res += toHtml(obj.nextElement()) + ", "; + } + res += "]"; + return res; + } else { + return obj; + } } }
--- a/src/share/classes/com/sun/tools/hat/resources/oqlhelp.html Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/com/sun/tools/hat/resources/oqlhelp.html Wed Aug 07 19:56:20 2013 -0700 @@ -79,7 +79,7 @@ <li>select all Strings of length 100 or more <pre> <code> - select s from java.lang.String s where s.count >= 100 + select s from java.lang.String s where s.value.length >= 100 </code> </pre> <li>select all int arrays of length 256 or more @@ -92,7 +92,7 @@ <pre> <code> select s.value.toString() from java.lang.String s - where /java/(s.value.toString()) + where /java/.test(s.value.toString()) </code> </pre> <li>show path value of all File objects @@ -219,7 +219,6 @@ <pre> <code> select heap.findClass("java.lang.System").statics.props - select heap.findClass("java.lang.System").props </code> </pre> <li>get number of fields of java.lang.String class @@ -237,7 +236,7 @@ <li>select all classes that have name pattern java.net.* <pre> <code> - select <a href="#filter">filter</a>(heap.classes(), "/java.net./(it.name)") + select <a href="#filter">filter</a>(heap.classes(), "/java.net./.test(it.name)") </code> </pre> </ul> @@ -536,7 +535,7 @@ Example: print number of classes that have specific name pattern <pre> <code> - select count(<a href="#classes">heap.classes()</a>, "/java.io./(it.name)") + select count(<a href="#classes">heap.classes()</a>, "/java.io./.test(it.name)") </code> </pre> @@ -559,14 +558,14 @@ <li>show all classes that have java.io.* name pattern <pre> <code> - select filter(<a href="#classes">heap.classes</a>(), "/java.io./(it.name)") + select filter(<a href="#classes">heap.classes</a>(), "/java.io./.test(it.name)") </code> </pre> <li> show all referrers of URL object where the referrer is not from java.net package <pre> <code> - select filter(<a href="#referrers">referrers</a>(u), "! /java.net./(<a href="#classof">classof</a>(it).name)") + select filter(<a href="#referrers">referrers</a>(u), "! /java.net./.test(<a href="#classof">classof</a>(it).name)") from java.net.URL u </code> </pre> @@ -619,13 +618,13 @@ <li>find the maximum length of any String instance <pre> <code> - select max(map(heap.objects('java.lang.String', false), 'it.count')) + select max(map(heap.objects('java.lang.String', false), 'it.value.length')) </code> </pre> <li>find string instance that has the maximum length <pre> <code> - select max(heap.objects('java.lang.String'), 'lhs.count > rhs.count') + select max(heap.objects('java.lang.String'), 'lhs.value.length > rhs.value.length') </code> </pre> </ul> @@ -775,7 +774,7 @@ <pre> <code> - select <a href="#map">map</a>(<a href="#filter">filter(<a href="#findClass">heap.findClass</a>('java.lang.System').props.table, 'it != null'), + select <a href="#map">map</a>(<a href="#filter">filter(<a href="#findClass">heap.findClass</a>('java.lang.System').statics.props.table, 'it != null'), function (it) { var res = ""; while (it != null) {
--- a/src/share/classes/java/applet/AppletContext.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/applet/AppletContext.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -56,7 +56,7 @@ /** * Returns an <code>Image</code> object that can then be painted on - * the screen. The <code>url</code> argument<code> </code>that is + * the screen. The <code>url</code> argument that is * passed as an argument must specify an absolute URL. * <p> * This method always returns immediately, whether or not the image @@ -157,7 +157,7 @@ * @param stream stream to be associated with the specified key. If this * parameter is <code>null</code>, the specified key is removed * in this applet context. - * @throws <code>IOException</code> if the stream size exceeds a certain + * @throws IOException if the stream size exceeds a certain * size limit. Size limit is decided by the implementor of this * interface. * @since 1.4
--- a/src/share/classes/java/beans/AppletInitializer.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/AppletInitializer.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -68,7 +68,6 @@ * the Applet with its Container during the subsequent invocation of its * addChildren() method. * </ol> - * </p> * * @param newAppletBean The newly instantiated JavaBean * @param bCtxt The BeanContext intended for this Applet, or
--- a/src/share/classes/java/beans/Beans.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/Beans.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -62,7 +62,7 @@ * <p> * Instantiate a JavaBean. * </p> - * + * @return a JavaBean * @param cls the class-loader from which we should create * the bean. If this is null, then the system * class-loader is used. @@ -82,6 +82,7 @@ * <p> * Instantiate a JavaBean. * </p> + * @return a JavaBean * * @param cls the class-loader from which we should create * the bean. If this is null, then the system @@ -137,6 +138,7 @@ * the JDK appletviewer (for a reference browser environment) and the * BDK BeanBox (for a reference bean container). * + * @return a JavaBean * @param cls the class-loader from which we should create * the bean. If this is null, then the system * class-loader is used. @@ -361,6 +363,8 @@ * This method is provided in Beans 1.0 as a hook to allow the * addition of more flexible bean behaviour in the future. * + * @return an object representing a specified type view of the + * source object * @param bean Object from which we want to obtain a view. * @param targetType The type of view we'd like to get. * @@ -384,7 +388,6 @@ return Introspector.isSubclass(bean.getClass(), targetType); } - /** * Test if we are in design-mode. *
--- a/src/share/classes/java/beans/ConstructorProperties.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/ConstructorProperties.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -61,7 +61,7 @@ the {@code getY()} method. Since parameter names are not in general available at runtime, without the annotation there would be no way to know whether the parameters correspond to {@code getX()} - and {@code getY()} or the other way around.</p> + and {@code getY()} or the other way around. @since 1.6 */
--- a/src/share/classes/java/beans/DefaultPersistenceDelegate.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/DefaultPersistenceDelegate.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, 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 @@ -382,6 +382,7 @@ * a class such that no property value depends on the value of * a subsequent property. * + * @param type the type of the instances * @param oldInstance The instance to be copied. * @param newInstance The instance that is to be modified. * @param out The stream to which any initialization statements should be written.
--- a/src/share/classes/java/beans/EventHandler.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/EventHandler.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, 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 @@ -515,6 +515,7 @@ *</pre> *</blockquote> * + * @param <T> the type to create * @param listenerInterface the listener interface to create a proxy for * @param target the object that will perform the action * @param action the name of a (possibly qualified) property or method on @@ -570,6 +571,7 @@ *</pre> *</blockquote> * + * @param <T> the type to create * @param listenerInterface the listener interface to create a proxy for * @param target the object that will perform the action * @param action the name of a (possibly qualified) property or method on @@ -659,6 +661,7 @@ * </pre> *</blockquote> * + * @param <T> the type to create * @param listenerInterface the listener interface to create a proxy for * @param target the object that will perform the action * @param action the name of a (possibly qualified) property or method on
--- a/src/share/classes/java/beans/Expression.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/Expression.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, 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 @@ -139,7 +139,7 @@ * replaces this default value in the same way that any other value * would, ensuring that expressions are never evaluated more than once. * <p> - * See the <code>excecute</code> method for details on how + * See the <code>execute</code> method for details on how * methods are chosen using the dynamic types of the target * and arguments. * @@ -147,6 +147,8 @@ * @see #setValue * * @return The result of applying this method to these arguments. + * @throws Exception if the method with the specified methodName + * throws an exception */ public Object getValue() throws Exception { if (value == unbound) {
--- a/src/share/classes/java/beans/IndexedPropertyDescriptor.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/IndexedPropertyDescriptor.java Wed Aug 07 19:56:20 2013 -0700 @@ -207,6 +207,8 @@ * Sets the method that should be used to read an indexed property value. * * @param readMethod The new indexed read method. + * @throws IntrospectionException if an exception occurs during + * introspection. */ public synchronized void setIndexedReadMethod(Method readMethod) throws IntrospectionException { @@ -285,6 +287,8 @@ * Sets the method that should be used to write an indexed property value. * * @param writeMethod The new indexed write method. + * @throws IntrospectionException if an exception occurs during + * introspection. */ public synchronized void setIndexedWriteMethod(Method writeMethod) throws IntrospectionException {
--- a/src/share/classes/java/beans/Introspector.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/Introspector.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -93,8 +93,17 @@ public class Introspector { // Flags that can be used to control getBeanInfo: + /** + * Flag to indicate to use of all beaninfo. + */ public final static int USE_ALL_BEANINFO = 1; + /** + * Flag to indicate to ignore immediate beaninfo. + */ public final static int IGNORE_IMMEDIATE_BEANINFO = 2; + /** + * Flag to indicate to ignore all beaninfo. + */ public final static int IGNORE_ALL_BEANINFO = 3; // Static Caches to speed up introspection. @@ -202,7 +211,7 @@ * If the BeanInfo class for a Java Bean has been previously Introspected * based on the same arguments, then the BeanInfo class is retrieved * from the BeanInfo cache. - * + * @return the BeanInfo for the bean * @param beanClass The bean class to be analyzed. * @param stopClass The baseclass at which to stop the analysis. Any * methods/properties/events in the stopClass or in its baseclasses
--- a/src/share/classes/java/beans/PersistenceDelegate.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/PersistenceDelegate.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, 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 @@ -197,6 +197,7 @@ * The default implementation, calls the <code>initialize</code> * method of the type's superclass. * + * @param type the type of the instances * @param oldInstance The instance to be copied. * @param newInstance The instance that is to be modified. * @param out The stream to which any initialization statements should be written.
--- a/src/share/classes/java/beans/PropertyChangeSupport.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/PropertyChangeSupport.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -156,7 +156,7 @@ * <code>PropertyChangeListenerProxy</code>, perform the cast, and examine * the parameter. * - * <pre> + * <pre>{@code * PropertyChangeListener[] listeners = bean.getPropertyChangeListeners(); * for (int i = 0; i < listeners.length; i++) { * if (listeners[i] instanceof PropertyChangeListenerProxy) { @@ -168,7 +168,7 @@ * } * } * } - *</pre> + * }</pre> * * @see PropertyChangeListenerProxy * @return all of the <code>PropertyChangeListeners</code> added or an
--- a/src/share/classes/java/beans/PropertyDescriptor.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/PropertyDescriptor.java Wed Aug 07 19:56:20 2013 -0700 @@ -243,6 +243,7 @@ * Sets the method that should be used to read the property value. * * @param readMethod The new read method. + * @throws IntrospectionException if the read method is invalid */ public synchronized void setReadMethod(Method readMethod) throws IntrospectionException { @@ -313,6 +314,7 @@ * Sets the method that should be used to write the property value. * * @param writeMethod The new write method. + * @throws IntrospectionException if the write method is invalid */ public synchronized void setWriteMethod(Method writeMethod) throws IntrospectionException {
--- a/src/share/classes/java/beans/Transient.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/Transient.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -40,7 +40,7 @@ * A {@code true} value for the "transient" attribute * indicates to encoders derived from {@link Encoder} * that this feature should be ignored. - * <p/> + * <p> * The {@code Transient} annotation may be be used * in any of the methods that are involved * in a {@link FeatureDescriptor} subclass @@ -49,7 +49,7 @@ * to put the annotation and it is this declaration * that takes precedence in the case of multiple annotations * being defined for the same feature. - * <p/> + * <p> * To declare a feature non-transient in a class * whose superclass declares it transient, * use {@code @Transient(false)}. @@ -64,5 +64,11 @@ @Target({METHOD}) @Retention(RUNTIME) public @interface Transient { + /** + * Returns whether or not the {@code Introspector} should + * construct artifacts for the annotated method. + * @return whether or not the {@code Introspector} should + * construct artifacts for the annotated method + */ boolean value() default true; }
--- a/src/share/classes/java/beans/VetoableChangeSupport.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/VetoableChangeSupport.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -42,7 +42,7 @@ * <p> * Here is an example of {@code VetoableChangeSupport} usage that follows * the rules and recommendations laid out in the JavaBeans™ specification: - * <pre> + * <pre>{@code * public class MyBean { * private final VetoableChangeSupport vcs = new VetoableChangeSupport(this); * @@ -68,7 +68,7 @@ * * [...] * } - * </pre> + * }</pre> * <p> * A {@code VetoableChangeSupport} instance is thread-safe. * <p> @@ -156,7 +156,7 @@ * <code>VetoableChangeListenerProxy</code>, perform the cast, and examine * the parameter. * - * <pre> + * <pre>{@code * VetoableChangeListener[] listeners = bean.getVetoableChangeListeners(); * for (int i = 0; i < listeners.length; i++) { * if (listeners[i] instanceof VetoableChangeListenerProxy) { @@ -168,7 +168,7 @@ * } * } * } - *</pre> + * }</pre> * * @see VetoableChangeListenerProxy * @return all of the <code>VetoableChangeListeners</code> added or an
--- a/src/share/classes/java/beans/beancontext/BeanContext.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/beancontext/BeanContext.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -64,10 +64,12 @@ * and is defined by the * <code>java.beans.Beans.instantiate()</code> method. * + * @return a javaBean named as a child of this + * <code>BeanContext</code> * @param beanName The name of the JavaBean to instantiate * as a child of this <code>BeanContext</code> - * @throws <code>IOException</code> - * @throws <code>ClassNotFoundException</code> if the class identified + * @throws IOException if an IO problem occurs + * @throws ClassNotFoundException if the class identified * by the beanName parameter is not found */ Object instantiateChild(String beanName) throws IOException, ClassNotFoundException; @@ -83,7 +85,7 @@ * @return an <code>InputStream</code> for reading the resource, * or <code>null</code> if the resource could not * be found. - * @throws <code>IllegalArgumentException</code> if + * @throws IllegalArgumentException if * the resource is not valid */ InputStream getResourceAsStream(String name, BeanContextChild bcc) throws IllegalArgumentException; @@ -98,7 +100,7 @@ * @param bcc the specified child * @return a <code>URL</code> for the named * resource for the specified child - * @throws <code>IllegalArgumentException</code> + * @throws IllegalArgumentException * if the resource is not valid */ URL getResource(String name, BeanContextChild bcc) throws IllegalArgumentException; @@ -109,7 +111,7 @@ * this <code>BeanContext</code> whenever it adds * or removes a child <code>Component</code>(s). * - * @param bcml the <code>BeanContextMembershipListener</code> to be added + * @param bcml the BeanContextMembershipListener to be added */ void addBeanContextMembershipListener(BeanContextMembershipListener bcml);
--- a/src/share/classes/java/beans/beancontext/BeanContextChild.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/beancontext/BeanContextChild.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -82,7 +82,7 @@ * </p> * @param bc The <code>BeanContext</code> with which * to associate this <code>BeanContextChild</code>. - * @throws <code>PropertyVetoException</code> if the + * @throws PropertyVetoException if the * addition of the specified <code>BeanContext</code> is refused. */ void setBeanContext(BeanContext bc) throws PropertyVetoException;
--- a/src/share/classes/java/beans/beancontext/BeanContextChildSupport.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/beancontext/BeanContextChildSupport.java Wed Aug 07 19:56:20 2013 -0700 @@ -78,6 +78,7 @@ * construct a BeanContextChildSupport where the JavaBean component * itself implements BeanContextChild, and encapsulates this, delegating * that interface to this implementation + * @param bcc the underlying bean context child */ public BeanContextChildSupport(BeanContextChild bcc) { @@ -94,7 +95,7 @@ * this <code>BeanContextChildSupport</code>. * @param bc the new value to be assigned to the <code>BeanContext</code> * property - * @throws <code>PropertyVetoException</code> if the change is rejected + * @throws PropertyVetoException if the change is rejected */ public synchronized void setBeanContext(BeanContext bc) throws PropertyVetoException { if (bc == beanContext) return; @@ -361,6 +362,9 @@ */ protected VetoableChangeSupport vcSupport; + /** + * The bean context. + */ protected transient BeanContext beanContext; /**
--- a/src/share/classes/java/beans/beancontext/BeanContextMembershipEvent.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/beancontext/BeanContextMembershipEvent.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -103,6 +103,7 @@ * Is the child specified affected by the event? * @return <code>true</code> if affected, <code>false</code> * if not + * @param child the object to check for being affected */ public boolean contains(Object child) { return children.contains(child);
--- a/src/share/classes/java/beans/beancontext/BeanContextServices.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/beancontext/BeanContextServices.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -60,6 +60,7 @@ * @param serviceClass the service to add * @param serviceProvider the <code>BeanContextServiceProvider</code> * associated with the service + * @return true if the service was successful added, false otherwise */ boolean addService(Class serviceClass, BeanContextServiceProvider serviceProvider); @@ -108,7 +109,7 @@ * @param bcsrl the * <code>BeanContextServiceRevokedListener</code> to notify * if the service should later become revoked - * @throws TooManyListenersException + * @throws TooManyListenersException if there are too many listeners * @return a reference to this context's named * Service as requested or <code>null</code> */
--- a/src/share/classes/java/beans/beancontext/BeanContextServicesSupport.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/beancontext/BeanContextServicesSupport.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -603,12 +603,16 @@ serviceProvider = bcsp; } + /** + * Returns the service provider. + * @return the service provider + */ protected BeanContextServiceProvider getServiceProvider() { return serviceProvider; } - /* - * fields + /** + * The service provider. */ protected BeanContextServiceProvider serviceProvider; @@ -618,6 +622,9 @@ * subclasses can override this method to create new subclasses of * BCSSServiceProvider without having to overrride addService() in * order to instantiate. + * @param sc the class + * @param bcsp the service provider + * @return a service provider without overriding addService() */ protected BCSSServiceProvider createBCSSServiceProvider(Class sc, BeanContextServiceProvider bcsp) { @@ -629,7 +636,7 @@ /** * add a BeanContextServicesListener * - * @throws NullPointerException + * @throws NullPointerException if the argument is null */ public void addBeanContextServicesListener(BeanContextServicesListener bcsl) { @@ -660,6 +667,8 @@ /** * add a service + * @param serviceClass the service class + * @param bcsp the service provider */ public boolean addService(Class serviceClass, BeanContextServiceProvider bcsp) { @@ -668,6 +677,10 @@ /** * add a service + * @param serviceClass the service class + * @param bcsp the service provider + * @param fireEvent whether or not an event should be fired + * @return true if the service was successfully added */ protected boolean addService(Class serviceClass, BeanContextServiceProvider bcsp, boolean fireEvent) { @@ -709,6 +722,9 @@ /** * remove a service + * @param serviceClass the service class + * @param bcsp the service provider + * @param revokeCurrentServicesNow whether or not to revoke the service */ public void revokeService(Class serviceClass, BeanContextServiceProvider bcsp, boolean revokeCurrentServicesNow) { @@ -1067,6 +1083,7 @@ /** * Fires a <tt>BeanContextServiceEvent</tt> notifying of a new service. + * @param serviceClass the service class */ protected final void fireServiceAdded(Class serviceClass) { BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass); @@ -1109,6 +1126,8 @@ * Fires a <tt>BeanContextServiceRevokedEvent</tt> * indicating that a particular service is * no longer available. + * @param serviceClass the service class + * @param revokeNow whether or not the event should be revoked now */ protected final void fireServiceRevoked(Class serviceClass, boolean revokeNow) { Object[] copy;
--- a/src/share/classes/java/beans/beancontext/BeanContextSupport.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/beans/beancontext/BeanContextSupport.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -62,7 +62,6 @@ /** * This helper class provides a utility implementation of the * java.beans.beancontext.BeanContext interface. - * </p> * <p> * Since this class directly implements the BeanContext interface, the class * can, and is intended to be used either by subclassing this implementation, @@ -351,9 +350,8 @@ * of Child without having to override add() or the other Collection * methods that add children to the set. * </p> - * * @param targetChild the child to create the Child on behalf of - * @param peer the peer if the tragetChild and the peer are related by an implementation of BeanContextProxy + * @param peer the peer if the tragetChild and the peer are related by an implementation of BeanContextProxy * @return Subtype-specific subclass of Child without overriding collection methods */ protected BCSChild createBCSChild(Object targetChild, Object peer) { @@ -492,6 +490,7 @@ * @param callChildSetBC used to indicate that * the child should be notified that it is no * longer nested in this <tt>BeanContext</tt>. + * @return whether or not was present before being removed */ protected boolean remove(Object targetChild, boolean callChildSetBC) { @@ -580,7 +579,8 @@ /** * add Collection to set of Children (Unsupported) * implementations must synchronized on the hierarchy lock and "children" protected field - * @throws UnsupportedOperationException + * @throws UnsupportedOperationException thrown unconditionally by this implementation + * @return this implementation unconditionally throws {@code UnsupportedOperationException} */ public boolean addAll(Collection c) { throw new UnsupportedOperationException(); @@ -589,7 +589,9 @@ /** * remove all specified children (Unsupported) * implementations must synchronized on the hierarchy lock and "children" protected field - * @throws UnsupportedOperationException + * @throws UnsupportedOperationException thrown unconditionally by this implementation + * @return this implementation unconditionally throws {@code UnsupportedOperationException} + */ public boolean removeAll(Collection c) { throw new UnsupportedOperationException(); @@ -599,7 +601,8 @@ /** * retain only specified children (Unsupported) * implementations must synchronized on the hierarchy lock and "children" protected field - * @throws UnsupportedOperationException + * @throws UnsupportedOperationException thrown unconditionally by this implementation + * @return this implementation unconditionally throws {@code UnsupportedOperationException} */ public boolean retainAll(Collection c) { throw new UnsupportedOperationException(); @@ -608,7 +611,7 @@ /** * clear the children (Unsupported) * implementations must synchronized on the hierarchy lock and "children" protected field - * @throws UnsupportedOperationException + * @throws UnsupportedOperationException thrown unconditionally by this implementation */ public void clear() { throw new UnsupportedOperationException(); @@ -618,7 +621,7 @@ * Adds a BeanContextMembershipListener * * @param bcml the BeanContextMembershipListener to add - * @throws NullPointerException + * @throws NullPointerException if the argument is null */ public void addBeanContextMembershipListener(BeanContextMembershipListener bcml) { @@ -636,7 +639,7 @@ * Removes a BeanContextMembershipListener * * @param bcml the BeanContextMembershipListener to remove - * @throws NullPointerException + * @throws NullPointerException if the argument is null */ public void removeBeanContextMembershipListener(BeanContextMembershipListener bcml) { @@ -655,7 +658,7 @@ * @param bcc the child object making the request. * * @return the requested resource as an InputStream - * @throws NullPointerException + * @throws NullPointerException if the argument is null */ public InputStream getResourceAsStream(String name, BeanContextChild bcc) { @@ -849,6 +852,8 @@ * * This method should not however be used by subclasses to replace their * own implementation (if any) of writeObject(). + * @param oos the {@code ObjectOutputStream} to use during serialization + * @throws IOException if serialization failed */ protected void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException { @@ -864,6 +869,9 @@ * * This method should not however be used by subclasses to replace their * own implementation (if any) of readObject(). + * @param ois the {@code ObjectInputStream} to use during deserialization + * @throws IOException if deserialization failed + * @throws ClassNotFoundException if needed classes are not found */ protected void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException { @@ -914,6 +922,8 @@ * used by readObject to deserialize a collection. * @param ois the ObjectInputStream to use * @param coll the Collection + * @throws IOException if deserialization failed + * @throws ClassNotFoundException if needed classes are not found */ protected final void deserialize(ObjectInputStream ois, Collection coll) throws IOException, ClassNotFoundException { int count = 0; @@ -1005,6 +1015,9 @@ * When an instance of this class is used as a delegate for the * implementation of the BeanContext protocols (and its subprotocols) * there exists a 'chicken and egg' problem during deserialization + * @param ois the ObjectInputStream to use + * @throws IOException if deserialization failed + * @throws ClassNotFoundException if needed classes are not found */ public final void readChildren(ObjectInputStream ois) throws IOException, ClassNotFoundException { @@ -1122,6 +1135,7 @@ * immediately prior to their being added to the BeanContext. * </p> * + * @param targetChild the child to create the Child on behalf of * @return true iff the child may be added to this BeanContext, otherwise false. */ @@ -1136,6 +1150,7 @@ * immediately prior to their being removed from the BeanContext. * </p> * + * @param targetChild the child to create the Child on behalf of * @return true iff the child may be removed from this BeanContext, otherwise false. */ @@ -1147,6 +1162,8 @@ * subclasses may override this method to simply extend add() semantics * after the child has been added and before the event notification has * occurred. The method is called with the child synchronized. + * @param child the child + * @param bcsc the BCSChild */ protected void childJustAddedHook(Object child, BCSChild bcsc) { @@ -1156,6 +1173,8 @@ * subclasses may override this method to simply extend remove() semantics * after the child has been removed and before the event notification has * occurred. The method is called with the child synchronized. + * @param child the child + * @param bcsc the BCSChild */ protected void childJustRemovedHook(Object child, BCSChild bcsc) { @@ -1254,6 +1273,7 @@ /** * Fire a BeanContextshipEvent on the BeanContextMembershipListener interface + * @param bcme the event to fire */ protected final void fireChildrenAdded(BeanContextMembershipEvent bcme) { @@ -1267,6 +1287,7 @@ /** * Fire a BeanContextshipEvent on the BeanContextMembershipListener interface + * @param bcme the event to fire */ protected final void fireChildrenRemoved(BeanContextMembershipEvent bcme) {
--- a/src/share/classes/java/net/SocketAddress.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/net/SocketAddress.java Wed Aug 07 19:56:20 2013 -0700 @@ -39,4 +39,7 @@ * @since 1.4 */ public abstract class SocketAddress implements java.io.Serializable { + + static final long serialVersionUID = 5215720748342549866L; + }
--- a/src/share/classes/java/nio/file/Files.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/nio/file/Files.java Wed Aug 07 19:56:20 2013 -0700 @@ -25,10 +25,10 @@ package java.nio.file; -import java.nio.ByteBuffer; import java.nio.file.attribute.*; import java.nio.file.spi.FileSystemProvider; import java.nio.file.spi.FileTypeDetector; +import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.SeekableByteChannel; import java.io.Closeable; @@ -2965,7 +2965,63 @@ } /** - * Read all the bytes from a file. The method ensures that the file is + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8; + + /** + * Reads all the bytes from an input stream. Uses {@code initialSize} as a hint + * about how many bytes the stream will have. + * + * @param source + * the input stream to read from + * @param initialSize + * the initial size of the byte array to allocate + * + * @return a byte array containing the bytes read from the file + * + * @throws IOException + * if an I/O error occurs reading from the stream + * @throws OutOfMemoryError + * if an array of the required size cannot be allocated + */ + private static byte[] read(InputStream source, int initialSize) + throws IOException + { + int capacity = initialSize; + byte[] buf = new byte[capacity]; + int nread = 0; + int n; + for (;;) { + // read to EOF which may read more or less than initialSize (eg: file + // is truncated while we are reading) + while ((n = source.read(buf, nread, capacity - nread)) > 0) + nread += n; + + // if last call to source.read() returned -1, we are done + // otherwise, try to read one more byte; if that failed we're done too + if (n < 0 || (n = source.read()) < 0) + break; + + // one more byte was read; need to allocate a larger buffer + if (capacity <= MAX_BUFFER_SIZE - capacity) { + capacity = Math.max(capacity << 1, BUFFER_SIZE); + } else { + if (capacity == MAX_BUFFER_SIZE) + throw new OutOfMemoryError("Required array size too large"); + capacity = MAX_BUFFER_SIZE; + } + buf = Arrays.copyOf(buf, capacity); + buf[nread++] = (byte)n; + } + return (capacity == nread) ? buf : Arrays.copyOf(buf, nread); + } + + /** + * Reads all the bytes from a file. The method ensures that the file is * closed when all bytes have been read or an I/O error, or other runtime * exception, is thrown. * @@ -2989,22 +3045,13 @@ * method is invoked to check read access to the file. */ public static byte[] readAllBytes(Path path) throws IOException { - try (FileChannel fc = FileChannel.open(path)) { + try (FileChannel fc = FileChannel.open(path); + InputStream is = Channels.newInputStream(fc)) { long size = fc.size(); - if (size > (long)Integer.MAX_VALUE) + if (size > (long)MAX_BUFFER_SIZE) throw new OutOfMemoryError("Required array size too large"); - byte[] arr = new byte[(int)size]; - ByteBuffer bb = ByteBuffer.wrap(arr); - while (bb.hasRemaining()) { - if (fc.read(bb) < 0) { - // truncated - break; - } - } - - int nread = bb.position(); - return (nread == size) ? arr : Arrays.copyOf(arr, nread); + return read(is, (int)size); } }
--- a/src/share/classes/java/rmi/server/RMISocketFactory.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/rmi/server/RMISocketFactory.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -33,15 +33,47 @@ * in order to obtain client and server sockets for RMI calls. An * application may use the <code>setSocketFactory</code> method to * request that the RMI runtime use its socket factory instance - * instead of the default implementation.<p> + * instead of the default implementation. * - * The default socket factory implementation used goes through a + * <p>The default socket factory implementation performs a * three-tiered approach to creating client sockets. First, a direct * socket connection to the remote VM is attempted. If that fails * (due to a firewall), the runtime uses HTTP with the explicit port * number of the server. If the firewall does not allow this type of * communication, then HTTP to a cgi-bin script on the server is used - * to POST the RMI call.<p> + * to POST the RMI call. + * + * <p>The default socket factory implementation creates server sockets that + * are bound to the wildcard address, which accepts requests from all network + * interfaces. + * + * @implNote + * <p>You can use the {@code RMISocketFactory} class to create a server socket that + * is bound to a specific address, restricting the origin of requests. For example, + * the following code implements a socket factory that binds server sockets to the + * loopback address. This restricts RMI to processing requests only from the local host. + * + * <pre>{@code + * class LoopbackSocketFactory extends RMISocketFactory { + * public ServerSocket createServerSocket(int port) throws IOException { + * return new ServerSocket(port, 5, InetAddress.getLoopbackAddress()); + * } + * + * public Socket createSocket(String host, int port) throws IOException { + * // just call the default client socket factory + * return RMISocketFactory.getDefaultSocketFactory() + * .createSocket(host, port); + * } + * } + * + * // ... + * + * RMISocketFactory.setSocketFactory(new LoopbackSocketFactory()); + * }</pre> + * + * Set the {@code java.rmi.server.hostname} system property + * to a host name (typically {@code localhost}) that resolves to the loopback + * interface to ensure that the generated stubs use the right network interface. * * @author Ann Wollrath * @author Peter Jones
--- a/src/share/classes/java/rmi/server/UnicastRemoteObject.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/rmi/server/UnicastRemoteObject.java Wed Aug 07 19:56:20 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -100,6 +100,26 @@ * </ul> * </ul> * + * <p>If an object is exported with the + * {@link #exportObject(Remote) exportObject(Remote)} + * or + * {@link #exportObject(Remote, int) exportObject(Remote, port)} + * methods, or if a subclass constructor invokes one of the + * {@link #UnicastRemoteObject()} + * or + * {@link #UnicastRemoteObject(int) UnicastRemoteObject(port)} + * constructors, the object is exported with a server socket created using the + * {@link RMISocketFactory} + * class. + * + * @implNote + * <p>By default, server sockets created by the {@link RMISocketFactory} class + * listen on all network interfaces. See the + * {@link RMISocketFactory} class and the section + * <a href="{@docRoot}/../platform/rmi/spec/rmi-server29.html">RMI Socket Factories</a> + * in the + * <a href="{@docRoot}/../platform/rmi/spec/rmiTOC.html">Java RMI Specification</a>. + * * @author Ann Wollrath * @author Peter Jones * @since JDK1.1
--- a/src/share/classes/java/security/Security.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/security/Security.java Wed Aug 07 19:56:20 2013 -0700 @@ -326,17 +326,13 @@ * * <p>A provider cannot be added if it is already installed. * - * <p>First, if there is a security manager, its - * {@code checkSecurityAccess} - * method is called with the string - * {@code "insertProvider."+provider.getName()} - * to see if it's ok to add a new provider. - * If the default implementation of {@code checkSecurityAccess} - * is used (i.e., that method is not overriden), then this will result in - * a call to the security manager's {@code checkPermission} method - * with a - * {@code SecurityPermission("insertProvider."+provider.getName())} - * permission. + * <p>If there is a security manager, the + * {@link java.lang.SecurityManager#checkSecurityAccess} method is called + * with the {@code "insertProvider"} permission target name to see if + * it's ok to add a new provider. If this permission check is denied, + * {@code checkSecurityAccess} is called again with the + * {@code "insertProvider."+provider.getName()} permission target name. If + * both checks are denied, a {@code SecurityException} is thrown. * * @param provider the provider to be added. * @@ -360,7 +356,7 @@ public static synchronized int insertProviderAt(Provider provider, int position) { String providerName = provider.getName(); - check("insertProvider." + providerName); + checkInsertProvider(providerName); ProviderList list = Providers.getFullProviderList(); ProviderList newList = ProviderList.insertAt(list, provider, position - 1); if (list == newList) { @@ -373,17 +369,13 @@ /** * Adds a provider to the next position available. * - * <p>First, if there is a security manager, its - * {@code checkSecurityAccess} - * method is called with the string - * {@code "insertProvider."+provider.getName()} - * to see if it's ok to add a new provider. - * If the default implementation of {@code checkSecurityAccess} - * is used (i.e., that method is not overriden), then this will result in - * a call to the security manager's {@code checkPermission} method - * with a - * {@code SecurityPermission("insertProvider."+provider.getName())} - * permission. + * <p>If there is a security manager, the + * {@link java.lang.SecurityManager#checkSecurityAccess} method is called + * with the {@code "insertProvider"} permission target name to see if + * it's ok to add a new provider. If this permission check is denied, + * {@code checkSecurityAccess} is called again with the + * {@code "insertProvider."+provider.getName()} permission target name. If + * both checks are denied, a {@code SecurityException} is thrown. * * @param provider the provider to be added. * @@ -863,6 +855,23 @@ } } + private static void checkInsertProvider(String name) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + try { + security.checkSecurityAccess("insertProvider"); + } catch (SecurityException se1) { + try { + security.checkSecurityAccess("insertProvider." + name); + } catch (SecurityException se2) { + // throw first exception, but add second to suppressed + se1.addSuppressed(se2); + throw se1; + } + } + } + } + /* * Returns all providers who satisfy the specified * criterion.
--- a/src/share/classes/java/security/SecurityPermission.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/security/SecurityPermission.java Wed Aug 07 19:56:20 2013 -0700 @@ -130,14 +130,17 @@ * </tr> * * <tr> - * <td>insertProvider.{provider name}</td> - * <td>Addition of a new provider, with the specified name</td> + * <td>insertProvider</td> + * <td>Addition of a new provider</td> * <td>This would allow somebody to introduce a possibly * malicious provider (e.g., one that discloses the private keys passed * to it) as the highest-priority provider. This would be possible * because the Security object (which manages the installed providers) * currently does not check the integrity or authenticity of a provider - * before attaching it.</td> + * before attaching it. The "insertProvider" permission subsumes the + * "insertProvider.{provider name}" permission (see the section below for + * more information). + * </td> * </tr> * * <tr> @@ -186,9 +189,10 @@ * </table> * * <P> - * The following permissions are associated with classes that have been - * deprecated: {@link Identity}, {@link IdentityScope}, {@link Signer}. Use of - * them is discouraged. See the applicable classes for more information. + * The following permissions have been superseded by newer permissions or are + * associated with classes that have been deprecated: {@link Identity}, + * {@link IdentityScope}, {@link Signer}. Use of them is discouraged. See the + * applicable classes for more information. * <P> * * <table border=1 cellpadding=5 summary="target name,what the permission allows, and associated risks"> @@ -199,6 +203,23 @@ * </tr> * * <tr> + * <td>insertProvider.{provider name}</td> + * <td>Addition of a new provider, with the specified name</td> + * <td>Use of this permission is discouraged from further use because it is + * possible to circumvent the name restrictions by overriding the + * {@link java.security.Provider#getName} method. Also, there is an equivalent + * level of risk associated with granting code permission to insert a provider + * with a specific name, or any name it chooses. Users should use the + * "insertProvider" permission instead. + * <p>This would allow somebody to introduce a possibly + * malicious provider (e.g., one that discloses the private keys passed + * to it) as the highest-priority provider. This would be possible + * because the Security object (which manages the installed providers) + * currently does not check the integrity or authenticity of a provider + * before attaching it.</td> + * </tr> + * + * <tr> * <td>setSystemScope</td> * <td>Setting of the system identity scope</td> * <td>This would allow an attacker to configure the system identity scope with @@ -306,7 +327,6 @@ * @throws NullPointerException if {@code name} is {@code null}. * @throws IllegalArgumentException if {@code name} is empty. */ - public SecurityPermission(String name) { super(name); @@ -323,7 +343,6 @@ * @throws NullPointerException if {@code name} is {@code null}. * @throws IllegalArgumentException if {@code name} is empty. */ - public SecurityPermission(String name, String actions) { super(name, actions);
--- a/src/share/classes/java/util/ArrayPrefixHelpers.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/ArrayPrefixHelpers.java Wed Aug 07 19:56:20 2013 -0700 @@ -128,6 +128,7 @@ this.lo = lo; this.hi = hi; } + @SuppressWarnings("unchecked") public final void compute() { final BinaryOperator<T> fn; final T[] a; @@ -692,6 +693,4 @@ } } } - - -} \ No newline at end of file +}
--- a/src/share/classes/java/util/Collections.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/Collections.java Wed Aug 07 19:56:20 2013 -0700 @@ -1143,6 +1143,7 @@ public boolean removeIf(Predicate<? super E> filter) { throw new UnsupportedOperationException(); } + @SuppressWarnings("unchecked") @Override public Spliterator<E> spliterator() { return (Spliterator<E>)c.spliterator(); @@ -1900,7 +1901,7 @@ private static final long serialVersionUID = -2239321462712562324L; - EmptyNavigableMap() { super(new TreeMap()); } + EmptyNavigableMap() { super(new TreeMap<K,V>()); } @Override public NavigableSet<K> navigableKeySet() @@ -1928,46 +1929,52 @@ public K ceilingKey(K key) { return nm.ceilingKey(key); } public K higherKey(K key) { return nm.higherKey(key); } + @SuppressWarnings("unchecked") public Entry<K, V> lowerEntry(K key) { Entry<K,V> lower = (Entry<K, V>) nm.lowerEntry(key); return (null != lower) - ? new UnmodifiableEntrySet.UnmodifiableEntry(lower) + ? new UnmodifiableEntrySet.UnmodifiableEntry<>(lower) : null; } + @SuppressWarnings("unchecked") public Entry<K, V> floorEntry(K key) { Entry<K,V> floor = (Entry<K, V>) nm.floorEntry(key); return (null != floor) - ? new UnmodifiableEntrySet.UnmodifiableEntry(floor) + ? new UnmodifiableEntrySet.UnmodifiableEntry<>(floor) : null; } + @SuppressWarnings("unchecked") public Entry<K, V> ceilingEntry(K key) { Entry<K,V> ceiling = (Entry<K, V>) nm.ceilingEntry(key); return (null != ceiling) - ? new UnmodifiableEntrySet.UnmodifiableEntry(ceiling) + ? new UnmodifiableEntrySet.UnmodifiableEntry<>(ceiling) : null; } + @SuppressWarnings("unchecked") public Entry<K, V> higherEntry(K key) { Entry<K,V> higher = (Entry<K, V>) nm.higherEntry(key); return (null != higher) - ? new UnmodifiableEntrySet.UnmodifiableEntry(higher) + ? new UnmodifiableEntrySet.UnmodifiableEntry<>(higher) : null; } + @SuppressWarnings("unchecked") public Entry<K, V> firstEntry() { Entry<K,V> first = (Entry<K, V>) nm.firstEntry(); return (null != first) - ? new UnmodifiableEntrySet.UnmodifiableEntry(first) + ? new UnmodifiableEntrySet.UnmodifiableEntry<>(first) : null; } + @SuppressWarnings("unchecked") public Entry<K, V> lastEntry() { Entry<K,V> last = (Entry<K, V>) nm.lastEntry(); return (null != last) - ? new UnmodifiableEntrySet.UnmodifiableEntry(last) + ? new UnmodifiableEntrySet.UnmodifiableEntry<>(last) : null; } @@ -2360,7 +2367,7 @@ } public NavigableSet<E> tailSet(E fromElement) { synchronized (mutex) { - return new SynchronizedNavigableSet(ns.tailSet(fromElement, true), mutex); + return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, true), mutex); } } @@ -2925,7 +2932,7 @@ public NavigableMap<K, V> descendingMap() { synchronized (mutex) { return - new SynchronizedNavigableMap(nm.descendingMap(), mutex); + new SynchronizedNavigableMap<>(nm.descendingMap(), mutex); } } @@ -2935,13 +2942,13 @@ public NavigableSet<K> navigableKeySet() { synchronized (mutex) { - return new SynchronizedNavigableSet(nm.navigableKeySet(), mutex); + return new SynchronizedNavigableSet<>(nm.navigableKeySet(), mutex); } } public NavigableSet<K> descendingKeySet() { synchronized (mutex) { - return new SynchronizedNavigableSet(nm.descendingKeySet(), mutex); + return new SynchronizedNavigableSet<>(nm.descendingKeySet(), mutex); } } @@ -2959,27 +2966,27 @@ } public SortedMap<K,V> tailMap(K fromKey) { synchronized (mutex) { - return new SynchronizedNavigableMap<>(nm.tailMap(fromKey, true),mutex); + return new SynchronizedNavigableMap<>(nm.tailMap(fromKey, true),mutex); } } public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { synchronized (mutex) { - return new SynchronizedNavigableMap( + return new SynchronizedNavigableMap<>( nm.subMap(fromKey, fromInclusive, toKey, toInclusive), mutex); } } public NavigableMap<K, V> headMap(K toKey, boolean inclusive) { synchronized (mutex) { - return new SynchronizedNavigableMap( + return new SynchronizedNavigableMap<>( nm.headMap(toKey, inclusive), mutex); } } public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) { synchronized (mutex) { - return new SynchronizedNavigableMap( + return new SynchronizedNavigableMap<>( nm.tailMap(fromKey, inclusive), mutex); } } @@ -4081,7 +4088,7 @@ public Entry<K, V> lowerEntry(K key) { Entry<K,V> lower = nm.lowerEntry(key); return (null != lower) - ? new CheckedMap.CheckedEntrySet.CheckedEntry(lower, valueType) + ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(lower, valueType) : null; } @@ -4090,7 +4097,7 @@ public Entry<K, V> floorEntry(K key) { Entry<K,V> floor = nm.floorEntry(key); return (null != floor) - ? new CheckedMap.CheckedEntrySet.CheckedEntry(floor, valueType) + ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(floor, valueType) : null; } @@ -4099,7 +4106,7 @@ public Entry<K, V> ceilingEntry(K key) { Entry<K,V> ceiling = nm.ceilingEntry(key); return (null != ceiling) - ? new CheckedMap.CheckedEntrySet.CheckedEntry(ceiling, valueType) + ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(ceiling, valueType) : null; } @@ -4108,7 +4115,7 @@ public Entry<K, V> higherEntry(K key) { Entry<K,V> higher = nm.higherEntry(key); return (null != higher) - ? new CheckedMap.CheckedEntrySet.CheckedEntry(higher, valueType) + ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(higher, valueType) : null; } @@ -4117,14 +4124,14 @@ public Entry<K, V> firstEntry() { Entry<K,V> first = nm.firstEntry(); return (null != first) - ? new CheckedMap.CheckedEntrySet.CheckedEntry(first, valueType) + ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(first, valueType) : null; } public Entry<K, V> lastEntry() { Entry<K,V> last = nm.lastEntry(); return (null != last) - ? new CheckedMap.CheckedEntrySet.CheckedEntry(last, valueType) + ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(last, valueType) : null; } @@ -4132,14 +4139,14 @@ Entry<K,V> entry = nm.pollFirstEntry(); return (null == entry) ? null - : new CheckedMap.CheckedEntrySet.CheckedEntry(entry, valueType); + : new CheckedMap.CheckedEntrySet.CheckedEntry<>(entry, valueType); } public Entry<K, V> pollLastEntry() { Entry<K,V> entry = nm.pollLastEntry(); return (null == entry) ? null - : new CheckedMap.CheckedEntrySet.CheckedEntry(entry, valueType); + : new CheckedMap.CheckedEntrySet.CheckedEntry<>(entry, valueType); } public NavigableMap<K, V> descendingMap() {
--- a/src/share/classes/java/util/Comparator.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/Comparator.java Wed Aug 07 19:56:20 2013 -0700 @@ -352,6 +352,7 @@ * @see Comparable * @since 1.8 */ + @SuppressWarnings("unchecked") public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() { return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE; } @@ -374,7 +375,7 @@ * @since 1.8 */ public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) { - return new Comparators.NullComparator(true, comparator); + return new Comparators.NullComparator<>(true, comparator); } /** @@ -395,7 +396,7 @@ * @since 1.8 */ public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) { - return new Comparators.NullComparator(false, comparator); + return new Comparators.NullComparator<>(false, comparator); } /**
--- a/src/share/classes/java/util/Comparators.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/Comparators.java Wed Aug 07 19:56:20 2013 -0700 @@ -87,12 +87,12 @@ @Override public Comparator<T> thenComparing(Comparator<? super T> other) { Objects.requireNonNull(other); - return new NullComparator(nullFirst, real == null ? other : real.thenComparing(other)); + return new NullComparator<>(nullFirst, real == null ? other : real.thenComparing(other)); } @Override public Comparator<T> reversed() { - return new NullComparator(!nullFirst, real == null ? null : real.reversed()); + return new NullComparator<>(!nullFirst, real == null ? null : real.reversed()); } } }
--- a/src/share/classes/java/util/Deque.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/Deque.java Wed Aug 07 19:56:20 2013 -0700 @@ -38,7 +38,7 @@ /** * A linear collection that supports element insertion and removal at * both ends. The name <i>deque</i> is short for "double ended queue" - * and is usually pronounced "deck". Most <tt>Deque</tt> + * and is usually pronounced "deck". Most {@code Deque} * implementations place no fixed limits on the number of elements * they may contain, but this interface supports capacity-restricted * deques as well as those with no fixed size limit. @@ -47,10 +47,10 @@ * ends of the deque. Methods are provided to insert, remove, and * examine the element. Each of these methods exists in two forms: * one throws an exception if the operation fails, the other returns a - * special value (either <tt>null</tt> or <tt>false</tt>, depending on + * special value (either {@code null} or {@code false}, depending on * the operation). The latter form of the insert operation is * designed specifically for use with capacity-restricted - * <tt>Deque</tt> implementations; in most implementations, insert + * {@code Deque} implementations; in most implementations, insert * operations cannot fail. * * <p>The twelve methods described above are summarized in the @@ -58,6 +58,7 @@ * * <p> * <table BORDER CELLPADDING=3 CELLSPACING=1> + * <caption>Summary of Deque methods</caption> * <tr> * <td></td> * <td ALIGN=CENTER COLSPAN = 2> <b>First Element (Head)</b></td> @@ -72,38 +73,39 @@ * </tr> * <tr> * <td><b>Insert</b></td> - * <td>{@link #addFirst addFirst(e)}</td> - * <td>{@link #offerFirst offerFirst(e)}</td> - * <td>{@link #addLast addLast(e)}</td> - * <td>{@link #offerLast offerLast(e)}</td> + * <td>{@link Deque#addFirst addFirst(e)}</td> + * <td>{@link Deque#offerFirst offerFirst(e)}</td> + * <td>{@link Deque#addLast addLast(e)}</td> + * <td>{@link Deque#offerLast offerLast(e)}</td> * </tr> * <tr> * <td><b>Remove</b></td> - * <td>{@link #removeFirst removeFirst()}</td> - * <td>{@link #pollFirst pollFirst()}</td> - * <td>{@link #removeLast removeLast()}</td> - * <td>{@link #pollLast pollLast()}</td> + * <td>{@link Deque#removeFirst removeFirst()}</td> + * <td>{@link Deque#pollFirst pollFirst()}</td> + * <td>{@link Deque#removeLast removeLast()}</td> + * <td>{@link Deque#pollLast pollLast()}</td> * </tr> * <tr> * <td><b>Examine</b></td> - * <td>{@link #getFirst getFirst()}</td> - * <td>{@link #peekFirst peekFirst()}</td> - * <td>{@link #getLast getLast()}</td> - * <td>{@link #peekLast peekLast()}</td> + * <td>{@link Deque#getFirst getFirst()}</td> + * <td>{@link Deque#peekFirst peekFirst()}</td> + * <td>{@link Deque#getLast getLast()}</td> + * <td>{@link Deque#peekLast peekLast()}</td> * </tr> * </table> * * <p>This interface extends the {@link Queue} interface. When a deque is * used as a queue, FIFO (First-In-First-Out) behavior results. Elements are * added at the end of the deque and removed from the beginning. The methods - * inherited from the <tt>Queue</tt> interface are precisely equivalent to - * <tt>Deque</tt> methods as indicated in the following table: + * inherited from the {@code Queue} interface are precisely equivalent to + * {@code Deque} methods as indicated in the following table: * * <p> * <table BORDER CELLPADDING=3 CELLSPACING=1> + * <caption>Comparison of Queue and Deque methods</caption> * <tr> - * <td ALIGN=CENTER> <b><tt>Queue</tt> Method</b></td> - * <td ALIGN=CENTER> <b>Equivalent <tt>Deque</tt> Method</b></td> + * <td ALIGN=CENTER> <b>{@code Queue} Method</b></td> + * <td ALIGN=CENTER> <b>Equivalent {@code Deque} Method</b></td> * </tr> * <tr> * <td>{@link java.util.Queue#add add(e)}</td> @@ -135,13 +137,14 @@ * interface should be used in preference to the legacy {@link Stack} class. * When a deque is used as a stack, elements are pushed and popped from the * beginning of the deque. Stack methods are precisely equivalent to - * <tt>Deque</tt> methods as indicated in the table below: + * {@code Deque} methods as indicated in the table below: * * <p> * <table BORDER CELLPADDING=3 CELLSPACING=1> + * <caption>Comparison of Stack and Deque methods</caption> * <tr> * <td ALIGN=CENTER> <b>Stack Method</b></td> - * <td ALIGN=CENTER> <b>Equivalent <tt>Deque</tt> Method</b></td> + * <td ALIGN=CENTER> <b>Equivalent {@code Deque} Method</b></td> * </tr> * <tr> * <td>{@link #push push(e)}</td> @@ -168,18 +171,18 @@ * <p>Unlike the {@link List} interface, this interface does not * provide support for indexed access to elements. * - * <p>While <tt>Deque</tt> implementations are not strictly required + * <p>While {@code Deque} implementations are not strictly required * to prohibit the insertion of null elements, they are strongly - * encouraged to do so. Users of any <tt>Deque</tt> implementations + * encouraged to do so. Users of any {@code Deque} implementations * that do allow null elements are strongly encouraged <i>not</i> to * take advantage of the ability to insert nulls. This is so because - * <tt>null</tt> is used as a special return value by various methods + * {@code null} is used as a special return value by various methods * to indicated that the deque is empty. * - * <p><tt>Deque</tt> implementations generally do not define - * element-based versions of the <tt>equals</tt> and <tt>hashCode</tt> + * <p>{@code Deque} implementations generally do not define + * element-based versions of the {@code equals} and {@code hashCode} * methods, but instead inherit the identity-based versions from class - * <tt>Object</tt>. + * {@code Object}. * * <p>This interface is a member of the <a * href="{@docRoot}/../technotes/guides/collections/index.html"> Java Collections @@ -190,13 +193,13 @@ * @since 1.6 * @param <E> the type of elements held in this collection */ - public interface Deque<E> extends Queue<E> { /** * Inserts the specified element at the front of this deque if it is - * possible to do so immediately without violating capacity restrictions. - * When using a capacity-restricted deque, it is generally preferable to - * use method {@link #offerFirst}. + * possible to do so immediately without violating capacity restrictions, + * throwing an {@code IllegalStateException} if no space is currently + * available. When using a capacity-restricted deque, it is generally + * preferable to use method {@link #offerFirst}. * * @param e the element to add * @throws IllegalStateException if the element cannot be added at this @@ -212,9 +215,10 @@ /** * Inserts the specified element at the end of this deque if it is - * possible to do so immediately without violating capacity restrictions. - * When using a capacity-restricted deque, it is generally preferable to - * use method {@link #offerLast}. + * possible to do so immediately without violating capacity restrictions, + * throwing an {@code IllegalStateException} if no space is currently + * available. When using a capacity-restricted deque, it is generally + * preferable to use method {@link #offerLast}. * * <p>This method is equivalent to {@link #add}. * @@ -237,8 +241,8 @@ * which can fail to insert an element only by throwing an exception. * * @param e the element to add - * @return <tt>true</tt> if the element was added to this deque, else - * <tt>false</tt> + * @return {@code true} if the element was added to this deque, else + * {@code false} * @throws ClassCastException if the class of the specified element * prevents it from being added to this deque * @throws NullPointerException if the specified element is null and this @@ -255,8 +259,8 @@ * which can fail to insert an element only by throwing an exception. * * @param e the element to add - * @return <tt>true</tt> if the element was added to this deque, else - * <tt>false</tt> + * @return {@code true} if the element was added to this deque, else + * {@code false} * @throws ClassCastException if the class of the specified element * prevents it from being added to this deque * @throws NullPointerException if the specified element is null and this @@ -288,17 +292,17 @@ /** * Retrieves and removes the first element of this deque, - * or returns <tt>null</tt> if this deque is empty. + * or returns {@code null} if this deque is empty. * - * @return the head of this deque, or <tt>null</tt> if this deque is empty + * @return the head of this deque, or {@code null} if this deque is empty */ E pollFirst(); /** * Retrieves and removes the last element of this deque, - * or returns <tt>null</tt> if this deque is empty. + * or returns {@code null} if this deque is empty. * - * @return the tail of this deque, or <tt>null</tt> if this deque is empty + * @return the tail of this deque, or {@code null} if this deque is empty */ E pollLast(); @@ -325,31 +329,31 @@ /** * Retrieves, but does not remove, the first element of this deque, - * or returns <tt>null</tt> if this deque is empty. + * or returns {@code null} if this deque is empty. * - * @return the head of this deque, or <tt>null</tt> if this deque is empty + * @return the head of this deque, or {@code null} if this deque is empty */ E peekFirst(); /** * Retrieves, but does not remove, the last element of this deque, - * or returns <tt>null</tt> if this deque is empty. + * or returns {@code null} if this deque is empty. * - * @return the tail of this deque, or <tt>null</tt> if this deque is empty + * @return the tail of this deque, or {@code null} if this deque is empty */ E peekLast(); /** * Removes the first occurrence of the specified element from this deque. * If the deque does not contain the element, it is unchanged. - * More formally, removes the first element <tt>e</tt> such that + * More formally, removes the first element {@code e} such that * <tt>(o==null ? e==null : o.equals(e))</tt> * (if such an element exists). - * Returns <tt>true</tt> if this deque contained the specified element + * Returns {@code true} if this deque contained the specified element * (or equivalently, if this deque changed as a result of the call). * * @param o element to be removed from this deque, if present - * @return <tt>true</tt> if an element was removed as a result of this call + * @return {@code true} if an element was removed as a result of this call * @throws ClassCastException if the class of the specified element * is incompatible with this deque * (<a href="Collection.html#optional-restrictions">optional</a>) @@ -362,14 +366,14 @@ /** * Removes the last occurrence of the specified element from this deque. * If the deque does not contain the element, it is unchanged. - * More formally, removes the last element <tt>e</tt> such that + * More formally, removes the last element {@code e} such that * <tt>(o==null ? e==null : o.equals(e))</tt> * (if such an element exists). - * Returns <tt>true</tt> if this deque contained the specified element + * Returns {@code true} if this deque contained the specified element * (or equivalently, if this deque changed as a result of the call). * * @param o element to be removed from this deque, if present - * @return <tt>true</tt> if an element was removed as a result of this call + * @return {@code true} if an element was removed as a result of this call * @throws ClassCastException if the class of the specified element * is incompatible with this deque * (<a href="Collection.html#optional-restrictions">optional</a>) @@ -385,15 +389,15 @@ * Inserts the specified element into the queue represented by this deque * (in other words, at the tail of this deque) if it is possible to do so * immediately without violating capacity restrictions, returning - * <tt>true</tt> upon success and throwing an - * <tt>IllegalStateException</tt> if no space is currently available. + * {@code true} upon success and throwing an + * {@code IllegalStateException} if no space is currently available. * When using a capacity-restricted deque, it is generally preferable to * use {@link #offer(Object) offer}. * * <p>This method is equivalent to {@link #addLast}. * * @param e the element to add - * @return <tt>true</tt> (as specified by {@link Collection#add}) + * @return {@code true} (as specified by {@link Collection#add}) * @throws IllegalStateException if the element cannot be added at this * time due to capacity restrictions * @throws ClassCastException if the class of the specified element @@ -409,7 +413,7 @@ * Inserts the specified element into the queue represented by this deque * (in other words, at the tail of this deque) if it is possible to do so * immediately without violating capacity restrictions, returning - * <tt>true</tt> upon success and <tt>false</tt> if no space is currently + * {@code true} upon success and {@code false} if no space is currently * available. When using a capacity-restricted deque, this method is * generally preferable to the {@link #add} method, which can fail to * insert an element only by throwing an exception. @@ -417,8 +421,8 @@ * <p>This method is equivalent to {@link #offerLast}. * * @param e the element to add - * @return <tt>true</tt> if the element was added to this deque, else - * <tt>false</tt> + * @return {@code true} if the element was added to this deque, else + * {@code false} * @throws ClassCastException if the class of the specified element * prevents it from being added to this deque * @throws NullPointerException if the specified element is null and this @@ -444,11 +448,11 @@ /** * Retrieves and removes the head of the queue represented by this deque * (in other words, the first element of this deque), or returns - * <tt>null</tt> if this deque is empty. + * {@code null} if this deque is empty. * * <p>This method is equivalent to {@link #pollFirst()}. * - * @return the first element of this deque, or <tt>null</tt> if + * @return the first element of this deque, or {@code null} if * this deque is empty */ E poll(); @@ -469,12 +473,12 @@ /** * Retrieves, but does not remove, the head of the queue represented by * this deque (in other words, the first element of this deque), or - * returns <tt>null</tt> if this deque is empty. + * returns {@code null} if this deque is empty. * * <p>This method is equivalent to {@link #peekFirst()}. * * @return the head of the queue represented by this deque, or - * <tt>null</tt> if this deque is empty + * {@code null} if this deque is empty */ E peek(); @@ -484,9 +488,8 @@ /** * Pushes an element onto the stack represented by this deque (in other * words, at the head of this deque) if it is possible to do so - * immediately without violating capacity restrictions, returning - * <tt>true</tt> upon success and throwing an - * <tt>IllegalStateException</tt> if no space is currently available. + * immediately without violating capacity restrictions, throwing an + * {@code IllegalStateException} if no space is currently available. * * <p>This method is equivalent to {@link #addFirst}. * @@ -520,16 +523,16 @@ /** * Removes the first occurrence of the specified element from this deque. * If the deque does not contain the element, it is unchanged. - * More formally, removes the first element <tt>e</tt> such that + * More formally, removes the first element {@code e} such that * <tt>(o==null ? e==null : o.equals(e))</tt> * (if such an element exists). - * Returns <tt>true</tt> if this deque contained the specified element + * Returns {@code true} if this deque contained the specified element * (or equivalently, if this deque changed as a result of the call). * - * <p>This method is equivalent to {@link #removeFirstOccurrence}. + * <p>This method is equivalent to {@link #removeFirstOccurrence(Object)}. * * @param o element to be removed from this deque, if present - * @return <tt>true</tt> if an element was removed as a result of this call + * @return {@code true} if an element was removed as a result of this call * @throws ClassCastException if the class of the specified element * is incompatible with this deque * (<a href="Collection.html#optional-restrictions">optional</a>) @@ -540,13 +543,13 @@ boolean remove(Object o); /** - * Returns <tt>true</tt> if this deque contains the specified element. - * More formally, returns <tt>true</tt> if and only if this deque contains - * at least one element <tt>e</tt> such that + * Returns {@code true} if this deque contains the specified element. + * More formally, returns {@code true} if and only if this deque contains + * at least one element {@code e} such that * <tt>(o==null ? e==null : o.equals(e))</tt>. * * @param o element whose presence in this deque is to be tested - * @return <tt>true</tt> if this deque contains the specified element + * @return {@code true} if this deque contains the specified element * @throws ClassCastException if the type of the specified element * is incompatible with this deque * (<a href="Collection.html#optional-restrictions">optional</a>)
--- a/src/share/classes/java/util/DoubleSummaryStatistics.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/DoubleSummaryStatistics.java Wed Aug 07 19:56:20 2013 -0700 @@ -25,6 +25,7 @@ package java.util; import java.util.function.DoubleConsumer; +import java.util.stream.Collector; /** * A state object for collecting statistics such as count, min, max, sum, and @@ -35,24 +36,24 @@ * summary statistics on a stream of doubles with: * <pre> {@code * DoubleSummaryStatistics stats = doubleStream.collect(DoubleSummaryStatistics::new, - * DoubleSummaryStatistics::accept, - * DoubleSummaryStatistics::combine); + * DoubleSummaryStatistics::accept, + * DoubleSummaryStatistics::combine); * }</pre> * * <p>{@code DoubleSummaryStatistics} can be used as a - * {@linkplain java.util.stream.Stream#reduce(java.util.function.BinaryOperator) reduction} + * {@linkplain java.util.stream.Stream#collect(Collector) reduction} * target for a {@linkplain java.util.stream.Stream stream}. For example: * * <pre> {@code * DoubleSummaryStatistics stats = people.stream() - * .collect(Collectors.toDoubleSummaryStatistics(Person::getWeight)); + * .collect(Collectors.summarizingDouble(Person::getWeight)); *}</pre> * * This computes, in a single pass, the count of people, as well as the minimum, * maximum, sum, and average of their weights. * * @implNote This implementation is not thread safe. However, it is safe to use - * {@link java.util.stream.Collectors#toDoubleSummaryStatistics(java.util.function.ToDoubleFunction) + * {@link java.util.stream.Collectors#summarizingDouble(java.util.function.ToDoubleFunction) * Collectors.toDoubleStatistics()} on a parallel stream, because the parallel * implementation of {@link java.util.stream.Stream#collect Stream.collect()} * provides the necessary partitioning, isolation, and merging of results for @@ -152,7 +153,7 @@ } /** - * Returns the average of values recorded, or zero if no values have been + * Returns the arithmetic mean of values recorded, or zero if no values have been * recorded. The average returned can vary depending upon the order in * which values are recorded. This is due to accumulated rounding error in * addition of values of differing magnitudes. Values sorted by increasing @@ -160,7 +161,7 @@ * value is a {@code NaN} or the sum is at any point a {@code NaN} then the * average will be {@code NaN}. * - * @return the average of values, or zero if none + * @return the arithmetic mean of values, or zero if none */ public final double getAverage() { return getCount() > 0 ? getSum() / getCount() : 0.0d;
--- a/src/share/classes/java/util/Formatter.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/Formatter.java Wed Aug 07 19:56:20 2013 -0700 @@ -626,12 +626,11 @@ * <p> For general argument types, the precision is the maximum number of * characters to be written to the output. * - * <p> For the floating-point conversions {@code 'e'}, {@code 'E'}, and - * {@code 'f'} the precision is the number of digits after the decimal - * separator. If the conversion is {@code 'g'} or {@code 'G'}, then the + * <p> For the floating-point conversions {@code 'a'}, {@code 'A'}, {@code 'e'}, + * {@code 'E'}, and {@code 'f'} the precision is the number of digits after the + * radix point. If the conversion is {@code 'g'} or {@code 'G'}, then the * precision is the total number of digits in the resulting magnitude after - * rounding. If the conversion is {@code 'a'} or {@code 'A'}, then the - * precision must not be specified. + * rounding. * * <p> For character, integral, and date/time argument types and the percent * and line separator conversions, the precision is not applicable; if a @@ -1297,14 +1296,21 @@ * of the significand as a fraction. The exponent is represented by * {@code 'p'} (<tt>'\u0070'</tt>) followed by a decimal string of the * unbiased exponent as if produced by invoking {@link - * Integer#toString(int) Integer.toString} on the exponent value. + * Integer#toString(int) Integer.toString} on the exponent value. If the + * precision is specified, the value is rounded to the given number of + * hexadecimal digits. * * <li> If <i>m</i> is a {@code double} value with a subnormal - * representation then the significand is represented by the characters - * {@code '0x0.'} followed by the hexadecimal representation of the rest - * of the significand as a fraction. The exponent is represented by - * {@code 'p-1022'}. Note that there must be at least one nonzero digit - * in a subnormal significand. + * representation then, unless the precision is specified to be in the range + * 1 through 12, inclusive, the significand is represented by the characters + * {@code '0x0.'} followed by the hexadecimal representation of the rest of + * the significand as a fraction, and the exponent represented by + * {@code 'p-1022'}. If the precision is in the interval + * [1, 12], the subnormal value is normalized such that it + * begins with the characters {@code '0x1.'}, rounded to the number of + * hexadecimal digits of precision, and the exponent adjusted + * accordingly. Note that there must be at least one nonzero digit in a + * subnormal significand. * * </ul> * @@ -1367,7 +1373,7 @@ * {@code 1}. * * <p> If the conversion is {@code 'a'} or {@code 'A'}, then the precision - * is the number of hexadecimal digits after the decimal separator. If the + * is the number of hexadecimal digits after the radix point. If the * precision is not provided, then all of the digits as returned by {@link * Double#toHexString(double)} will be output. *
--- a/src/share/classes/java/util/HashMap.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/HashMap.java Wed Aug 07 19:56:20 2013 -0700 @@ -876,13 +876,9 @@ private static int roundUpToPowerOf2(int number) { // assert number >= 0 : "number must be non-negative"; - int rounded = number >= MAXIMUM_CAPACITY + return number >= MAXIMUM_CAPACITY ? MAXIMUM_CAPACITY - : (rounded = Integer.highestOneBit(number)) != 0 - ? (Integer.bitCount(number) > 1) ? rounded << 1 : rounded - : 1; - - return rounded; + : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1; } /**
--- a/src/share/classes/java/util/Hashtable.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/Hashtable.java Wed Aug 07 19:56:20 2013 -0700 @@ -928,6 +928,7 @@ return (null == result) ? defaultValue : result; } + @SuppressWarnings("unchecked") @Override public synchronized void forEach(BiConsumer<? super K, ? super V> action) { Objects.requireNonNull(action); // explicit check required in case @@ -947,6 +948,7 @@ } } + @SuppressWarnings("unchecked") @Override public synchronized void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { Objects.requireNonNull(function); // explicit check required in case
--- a/src/share/classes/java/util/IdentityHashMap.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/IdentityHashMap.java Wed Aug 07 19:56:20 2013 -0700 @@ -1339,6 +1339,7 @@ tab[i + 1] = value; } + @SuppressWarnings("unchecked") @Override public void forEach(BiConsumer<? super K, ? super V> action) { Objects.requireNonNull(action); @@ -1357,6 +1358,7 @@ } } + @SuppressWarnings("unchecked") @Override public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { Objects.requireNonNull(function);
--- a/src/share/classes/java/util/IntSummaryStatistics.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/IntSummaryStatistics.java Wed Aug 07 19:56:20 2013 -0700 @@ -25,6 +25,7 @@ package java.util; import java.util.function.IntConsumer; +import java.util.stream.Collector; /** * A state object for collecting statistics such as count, min, max, sum, and @@ -35,24 +36,24 @@ * summary statistics on a stream of ints with: * <pre> {@code * IntSummaryStatistics stats = intStream.collect(IntSummaryStatistics::new, - * IntSummaryStatistics::accept, - * IntSummaryStatistics::combine); + * IntSummaryStatistics::accept, + * IntSummaryStatistics::combine); * }</pre> * * <p>{@code IntSummaryStatistics} can be used as a - * {@linkplain java.util.stream.Stream#reduce(java.util.function.BinaryOperator) reduction} + * {@linkplain java.util.stream.Stream#collect(Collector) reduction} * target for a {@linkplain java.util.stream.Stream stream}. For example: * * <pre> {@code * IntSummaryStatistics stats = people.stream() - * .collect(Collectors.toIntSummaryStatistics(Person::getDependents)); + * .collect(Collectors.summarizingInt(Person::getDependents)); *}</pre> * * This computes, in a single pass, the count of people, as well as the minimum, * maximum, sum, and average of their number of dependents. * * @implNote This implementation is not thread safe. However, it is safe to use - * {@link java.util.stream.Collectors#toIntSummaryStatistics(java.util.function.ToIntFunction) + * {@link java.util.stream.Collectors#summarizingInt(java.util.function.ToIntFunction) * Collectors.toIntStatistics()} on a parallel stream, because the parallel * implementation of {@link java.util.stream.Stream#collect Stream.collect()} * provides the necessary partitioning, isolation, and merging of results for @@ -140,10 +141,10 @@ } /** - * Returns the average of values recorded, or zero if no values have been + * Returns the arithmetic mean of values recorded, or zero if no values have been * recorded. * - * @return the average of values, or zero if none + * @return the arithmetic mean of values, or zero if none */ public final double getAverage() { return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
--- a/src/share/classes/java/util/LongSummaryStatistics.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/LongSummaryStatistics.java Wed Aug 07 19:56:20 2013 -0700 @@ -26,6 +26,7 @@ import java.util.function.IntConsumer; import java.util.function.LongConsumer; +import java.util.stream.Collector; /** * A state object for collecting statistics such as count, min, max, sum, and @@ -36,24 +37,24 @@ * summary statistics on a stream of longs with: * <pre> {@code * LongSummaryStatistics stats = longStream.collect(LongSummaryStatistics::new, - * LongSummaryStatistics::accept, - * LongSummaryStatistics::combine); + * LongSummaryStatistics::accept, + * LongSummaryStatistics::combine); * }</pre> * * <p>{@code LongSummaryStatistics} can be used as a - * {@linkplain java.util.stream.Stream#reduce(java.util.function.BinaryOperator) reduction} + * {@linkplain java.util.stream.Stream#collect(Collector)} reduction} * target for a {@linkplain java.util.stream.Stream stream}. For example: * * <pre> {@code * LongSummaryStatistics stats = people.stream() - * .collect(Collectors.toLongSummaryStatistics(Person::getAge)); + * .collect(Collectors.summarizingLong(Person::getAge)); *}</pre> * * This computes, in a single pass, the count of people, as well as the minimum, - * maximum, sum, and average of their ages in milliseconds. + * maximum, sum, and average of their ages. * * @implNote This implementation is not thread safe. However, it is safe to use - * {@link java.util.stream.Collectors#toLongSummaryStatistics(java.util.function.ToLongFunction) + * {@link java.util.stream.Collectors#summarizingLong(java.util.function.ToLongFunction) * Collectors.toLongStatistics()} on a parallel stream, because the parallel * implementation of {@link java.util.stream.Stream#collect Stream.collect()} * provides the necessary partitioning, isolation, and merging of results for @@ -152,10 +153,10 @@ } /** - * Returns the average of values recorded, or zero if no values have been + * Returns the arithmetic mean of values recorded, or zero if no values have been * recorded. * - * @return The average of values, or zero if none + * @return The arithmetic mean of values, or zero if none */ public final double getAverage() { return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
--- a/src/share/classes/java/util/Optional.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/Optional.java Wed Aug 07 19:56:20 2013 -0700 @@ -307,7 +307,7 @@ return false; } - Optional other = (Optional) obj; + Optional<?> other = (Optional<?>) obj; return Objects.equals(value, other.value); }
--- a/src/share/classes/java/util/Queue.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/Queue.java Wed Aug 07 19:56:20 2013 -0700 @@ -41,14 +41,15 @@ * queues provide additional insertion, extraction, and inspection * operations. Each of these methods exists in two forms: one throws * an exception if the operation fails, the other returns a special - * value (either <tt>null</tt> or <tt>false</tt>, depending on the + * value (either {@code null} or {@code false}, depending on the * operation). The latter form of the insert operation is designed - * specifically for use with capacity-restricted <tt>Queue</tt> + * specifically for use with capacity-restricted {@code Queue} * implementations; in most implementations, insert operations cannot * fail. * * <p> * <table BORDER CELLPADDING=3 CELLSPACING=1> + * <caption>Summary of Queue methods</caption> * <tr> * <td></td> * <td ALIGN=CENTER><em>Throws exception</em></td> @@ -56,18 +57,18 @@ * </tr> * <tr> * <td><b>Insert</b></td> - * <td>{@link #add add(e)}</td> - * <td>{@link #offer offer(e)}</td> + * <td>{@link Queue#add add(e)}</td> + * <td>{@link Queue#offer offer(e)}</td> * </tr> * <tr> * <td><b>Remove</b></td> - * <td>{@link #remove remove()}</td> - * <td>{@link #poll poll()}</td> + * <td>{@link Queue#remove remove()}</td> + * <td>{@link Queue#poll poll()}</td> * </tr> * <tr> * <td><b>Examine</b></td> - * <td>{@link #element element()}</td> - * <td>{@link #peek peek()}</td> + * <td>{@link Queue#element element()}</td> + * <td>{@link Queue#peek peek()}</td> * </tr> * </table> * @@ -79,15 +80,15 @@ * Whatever the ordering used, the <em>head</em> of the queue is that * element which would be removed by a call to {@link #remove() } or * {@link #poll()}. In a FIFO queue, all new elements are inserted at - * the <em> tail</em> of the queue. Other kinds of queues may use - * different placement rules. Every <tt>Queue</tt> implementation + * the <em>tail</em> of the queue. Other kinds of queues may use + * different placement rules. Every {@code Queue} implementation * must specify its ordering properties. * * <p>The {@link #offer offer} method inserts an element if possible, - * otherwise returning <tt>false</tt>. This differs from the {@link + * otherwise returning {@code false}. This differs from the {@link * java.util.Collection#add Collection.add} method, which can fail to * add an element only by throwing an unchecked exception. The - * <tt>offer</tt> method is designed for use when failure is a normal, + * {@code offer} method is designed for use when failure is a normal, * rather than exceptional occurrence, for example, in fixed-capacity * (or "bounded") queues. * @@ -95,32 +96,32 @@ * return the head of the queue. * Exactly which element is removed from the queue is a * function of the queue's ordering policy, which differs from - * implementation to implementation. The <tt>remove()</tt> and - * <tt>poll()</tt> methods differ only in their behavior when the - * queue is empty: the <tt>remove()</tt> method throws an exception, - * while the <tt>poll()</tt> method returns <tt>null</tt>. + * implementation to implementation. The {@code remove()} and + * {@code poll()} methods differ only in their behavior when the + * queue is empty: the {@code remove()} method throws an exception, + * while the {@code poll()} method returns {@code null}. * * <p>The {@link #element()} and {@link #peek()} methods return, but do * not remove, the head of the queue. * - * <p>The <tt>Queue</tt> interface does not define the <i>blocking queue + * <p>The {@code Queue} interface does not define the <i>blocking queue * methods</i>, which are common in concurrent programming. These methods, * which wait for elements to appear or for space to become available, are * defined in the {@link java.util.concurrent.BlockingQueue} interface, which * extends this interface. * - * <p><tt>Queue</tt> implementations generally do not allow insertion - * of <tt>null</tt> elements, although some implementations, such as - * {@link LinkedList}, do not prohibit insertion of <tt>null</tt>. - * Even in the implementations that permit it, <tt>null</tt> should - * not be inserted into a <tt>Queue</tt>, as <tt>null</tt> is also - * used as a special return value by the <tt>poll</tt> method to + * <p>{@code Queue} implementations generally do not allow insertion + * of {@code null} elements, although some implementations, such as + * {@link LinkedList}, do not prohibit insertion of {@code null}. + * Even in the implementations that permit it, {@code null} should + * not be inserted into a {@code Queue}, as {@code null} is also + * used as a special return value by the {@code poll} method to * indicate that the queue contains no elements. * - * <p><tt>Queue</tt> implementations generally do not define - * element-based versions of methods <tt>equals</tt> and - * <tt>hashCode</tt> but instead inherit the identity based versions - * from class <tt>Object</tt>, because element-based equality is not + * <p>{@code Queue} implementations generally do not define + * element-based versions of methods {@code equals} and + * {@code hashCode} but instead inherit the identity based versions + * from class {@code Object}, because element-based equality is not * always well-defined for queues with the same elements but different * ordering properties. * @@ -145,11 +146,11 @@ /** * Inserts the specified element into this queue if it is possible to do so * immediately without violating capacity restrictions, returning - * <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt> + * {@code true} upon success and throwing an {@code IllegalStateException} * if no space is currently available. * * @param e the element to add - * @return <tt>true</tt> (as specified by {@link Collection#add}) + * @return {@code true} (as specified by {@link Collection#add}) * @throws IllegalStateException if the element cannot be added at this * time due to capacity restrictions * @throws ClassCastException if the class of the specified element @@ -169,8 +170,8 @@ * by throwing an exception. * * @param e the element to add - * @return <tt>true</tt> if the element was added to this queue, else - * <tt>false</tt> + * @return {@code true} if the element was added to this queue, else + * {@code false} * @throws ClassCastException if the class of the specified element * prevents it from being added to this queue * @throws NullPointerException if the specified element is null and @@ -192,9 +193,9 @@ /** * Retrieves and removes the head of this queue, - * or returns <tt>null</tt> if this queue is empty. + * or returns {@code null} if this queue is empty. * - * @return the head of this queue, or <tt>null</tt> if this queue is empty + * @return the head of this queue, or {@code null} if this queue is empty */ E poll(); @@ -210,9 +211,9 @@ /** * Retrieves, but does not remove, the head of this queue, - * or returns <tt>null</tt> if this queue is empty. + * or returns {@code null} if this queue is empty. * - * @return the head of this queue, or <tt>null</tt> if this queue is empty + * @return the head of this queue, or {@code null} if this queue is empty */ E peek(); }
--- a/src/share/classes/java/util/StringJoiner.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/StringJoiner.java Wed Aug 07 19:56:20 2013 -0700 @@ -49,16 +49,17 @@ * <p> * A {@code StringJoiner} may be employed to create formatted output from a * {@link java.util.stream.Stream} using - * {@link java.util.stream.Collectors#toStringJoiner}. For example: + * {@link java.util.stream.Collectors#joining(CharSequence)}. For example: * * <pre> {@code * List<Integer> numbers = Arrays.asList(1, 2, 3, 4); * String commaSeparatedNumbers = numbers.stream() * .map(i -> i.toString()) - * .collect(Collectors.toStringJoiner(", ")).toString(); + * .collect(Collectors.joining(", ")); * }</pre> * - * @see java.util.stream.Collectors#toStringJoiner + * @see java.util.stream.Collectors#joining(CharSequence) + * @see java.util.stream.Collectors#joining(CharSequence, CharSequence, CharSequence) * @since 1.8 */ public final class StringJoiner {
--- a/src/share/classes/java/util/Vector.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/Vector.java Wed Aug 07 19:56:20 2013 -0700 @@ -1164,12 +1164,13 @@ if (i >= size) { return; } - final Object[] elementData = Vector.this.elementData; + @SuppressWarnings("unchecked") + final E[] elementData = (E[]) Vector.this.elementData; if (i >= elementData.length) { throw new ConcurrentModificationException(); } while (i != size && modCount == expectedModCount) { - action.accept((E) elementData[i++]); + action.accept(elementData[i++]); } // update once at end of iteration to reduce heap write traffic cursor = i; @@ -1311,8 +1312,8 @@ modCount++; } + @SuppressWarnings("unchecked") @Override - @SuppressWarnings("unchecked") public synchronized void sort(Comparator<? super E> c) { final int expectedModCount = modCount; Arrays.sort((E[]) elementData, 0, elementCount, c);
--- a/src/share/classes/java/util/WeakHashMap.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/WeakHashMap.java Wed Aug 07 19:56:20 2013 -0700 @@ -1038,6 +1038,7 @@ } } + @SuppressWarnings("unchecked") @Override public void forEach(BiConsumer<? super K, ? super V> action) { Objects.requireNonNull(action); @@ -1059,6 +1060,7 @@ } } + @SuppressWarnings("unchecked") @Override public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { Objects.requireNonNull(function);
--- a/src/share/classes/java/util/concurrent/CompletableFuture.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/concurrent/CompletableFuture.java Wed Aug 07 19:56:20 2013 -0700 @@ -48,13 +48,16 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.LockSupport; /** * A {@link Future} that may be explicitly completed (setting its - * value and status), and may include dependent functions and actions - * that trigger upon its completion. + * value and status), and may be used as a {@link CompletionStage}, + * supporting dependent functions and actions that trigger upon its + * completion. * * <p>When two or more threads attempt to * {@link #complete complete}, @@ -62,64 +65,50 @@ * {@link #cancel cancel} * a CompletableFuture, only one of them succeeds. * - * <p>Methods are available for adding dependents based on - * user-provided Functions, Consumers, or Runnables. The appropriate - * form to use depends on whether actions require arguments and/or - * produce results. Completion of a dependent action will trigger the - * completion of another CompletableFuture. Actions may also be - * triggered after either or both the current and another - * CompletableFuture complete. Multiple CompletableFutures may also - * be grouped as one using {@link #anyOf(CompletableFuture...)} and - * {@link #allOf(CompletableFuture...)}. + * <p>In addition to these and related methods for directly + * manipulating status and results, CompletableFuture implements + * interface {@link CompletionStage} with the following policies: <ul> * - * <p>CompletableFutures themselves do not execute asynchronously. - * However, actions supplied for dependent completions of another - * CompletableFuture may do so, depending on whether they are provided - * via one of the <em>async</em> methods (that is, methods with names - * of the form <tt><var>xxx</var>Async</tt>). The <em>async</em> - * methods provide a way to commence asynchronous processing of an - * action using either a given {@link Executor} or by default the - * {@link ForkJoinPool#commonPool()}. To simplify monitoring, + * <li>Actions supplied for dependent completions of + * <em>non-async</em> methods may be performed by the thread that + * completes the current CompletableFuture, or by any other caller of + * a completion method.</li> + * + * <li>All <em>async</em> methods without an explicit Executor + * argument are performed using the {@link ForkJoinPool#commonPool()} + * (unless it does not support a parallelism level of at least two, in + * which case, a new Thread is used). To simplify monitoring, * debugging, and tracking, all generated asynchronous tasks are - * instances of the marker interface {@link AsynchronousCompletionTask}. + * instances of the marker interface {@link + * AsynchronousCompletionTask}. </li> * - * <p>Actions supplied for dependent completions of <em>non-async</em> - * methods may be performed by the thread that completes the current - * CompletableFuture, or by any other caller of these methods. There - * are no guarantees about the order of processing completions unless - * constrained by these methods. + * <li>All CompletionStage methods are implemented independently of + * other public methods, so the behavior of one method is not impacted + * by overrides of others in subclasses. </li> </ul> * - * <p>Since (unlike {@link FutureTask}) this class has no direct + * <p>CompletableFuture also implements {@link Future} with the following + * policies: <ul> + * + * <li>Since (unlike {@link FutureTask}) this class has no direct * control over the computation that causes it to be completed, - * cancellation is treated as just another form of exceptional completion. - * Method {@link #cancel cancel} has the same effect as - * {@code completeExceptionally(new CancellationException())}. + * cancellation is treated as just another form of exceptional + * completion. Method {@link #cancel cancel} has the same effect as + * {@code completeExceptionally(new CancellationException())}. Method + * {@link #isCompletedExceptionally} can be used to determine if a + * CompletableFuture completed in any exceptional fashion.</li> * - * <p>Upon exceptional completion (including cancellation), or when a - * completion entails an additional computation which terminates - * abruptly with an (unchecked) exception or error, then all of their - * dependent completions (and their dependents in turn) generally act - * as {@code completeExceptionally} with a {@link CompletionException} - * holding that exception as its cause. However, the {@link - * #exceptionally exceptionally} and {@link #handle handle} - * completions <em>are</em> able to handle exceptional completions of - * the CompletableFutures they depend on. - * - * <p>In case of exceptional completion with a CompletionException, + * <li>In case of exceptional completion with a CompletionException, * methods {@link #get()} and {@link #get(long, TimeUnit)} throw an * {@link ExecutionException} with the same cause as held in the - * corresponding CompletionException. However, in these cases, - * methods {@link #join()} and {@link #getNow} throw the - * CompletionException, which simplifies usage. - * - * <p>Arguments used to pass a completion result (that is, for parameters - * of type {@code T}) may be null, but passing a null value for any other - * parameter will result in a {@link NullPointerException} being thrown. + * corresponding CompletionException. To simplify usage in most + * contexts, this class also defines methods {@link #join()} and + * {@link #getNow} that instead throw the CompletionException directly + * in these cases.</li> </ul> * * @author Doug Lea * @since 1.8 */ -public class CompletableFuture<T> implements Future<T> { +public class CompletableFuture<T> implements Future<T>, CompletionStage<T> { /* * Overview: @@ -438,6 +427,19 @@ public final void run() { exec(); } } + /** + * Starts the given async task using the given executor, unless + * the executor is ForkJoinPool.commonPool and it has been + * disabled, in which case starts a new thread. + */ + static void execAsync(Executor e, Async r) { + if (e == ForkJoinPool.commonPool() && + ForkJoinPool.getCommonPoolParallelism() <= 1) + new Thread(r).start(); + else + e.execute(r); + } + static final class AsyncRun extends Async { final Runnable fn; final CompletableFuture<Void> dst; @@ -538,13 +540,13 @@ static final class AsyncAccept<T> extends Async { final T arg; final Consumer<? super T> fn; - final CompletableFuture<Void> dst; + final CompletableFuture<?> dst; AsyncAccept(T arg, Consumer<? super T> fn, - CompletableFuture<Void> dst) { + CompletableFuture<?> dst) { this.arg = arg; this.fn = fn; this.dst = dst; } public final boolean exec() { - CompletableFuture<Void> d; Throwable ex; + CompletableFuture<?> d; Throwable ex; if ((d = this.dst) != null && d.result == null) { try { fn.accept(arg); @@ -563,14 +565,14 @@ final T arg1; final U arg2; final BiConsumer<? super T,? super U> fn; - final CompletableFuture<Void> dst; + final CompletableFuture<?> dst; AsyncAcceptBoth(T arg1, U arg2, BiConsumer<? super T,? super U> fn, - CompletableFuture<Void> dst) { + CompletableFuture<?> dst) { this.arg1 = arg1; this.arg2 = arg2; this.fn = fn; this.dst = dst; } public final boolean exec() { - CompletableFuture<Void> d; Throwable ex; + CompletableFuture<?> d; Throwable ex; if ((d = this.dst) != null && d.result == null) { try { fn.accept(arg1, arg2); @@ -587,10 +589,10 @@ static final class AsyncCompose<T,U> extends Async { final T arg; - final Function<? super T, CompletableFuture<U>> fn; + final Function<? super T, ? extends CompletionStage<U>> fn; final CompletableFuture<U> dst; AsyncCompose(T arg, - Function<? super T, CompletableFuture<U>> fn, + Function<? super T, ? extends CompletionStage<U>> fn, CompletableFuture<U> dst) { this.arg = arg; this.fn = fn; this.dst = dst; } @@ -598,7 +600,8 @@ CompletableFuture<U> d, fr; U u; Throwable ex; if ((d = this.dst) != null && d.result == null) { try { - fr = fn.apply(arg); + CompletionStage<U> cs = fn.apply(arg); + fr = (cs == null) ? null : cs.toCompletableFuture(); ex = (fr == null) ? new NullPointerException() : null; } catch (Throwable rex) { ex = rex; @@ -626,6 +629,33 @@ private static final long serialVersionUID = 5232453952276885070L; } + static final class AsyncWhenComplete<T> extends Async { + final T arg1; + final Throwable arg2; + final BiConsumer<? super T,? super Throwable> fn; + final CompletableFuture<T> dst; + AsyncWhenComplete(T arg1, Throwable arg2, + BiConsumer<? super T,? super Throwable> fn, + CompletableFuture<T> dst) { + this.arg1 = arg1; this.arg2 = arg2; this.fn = fn; this.dst = dst; + } + public final boolean exec() { + CompletableFuture<T> d; + if ((d = this.dst) != null && d.result == null) { + Throwable ex = arg2; + try { + fn.accept(arg1, ex); + } catch (Throwable rex) { + if (ex == null) + ex = rex; + } + d.internalComplete(arg1, ex); + } + return true; + } + private static final long serialVersionUID = 5232453952276885070L; + } + /* ------------- Completions -------------- */ /** @@ -680,7 +710,7 @@ if (ex == null) { try { if (e != null) - e.execute(new AsyncApply<T,U>(t, fn, dst)); + execAsync(e, new AsyncApply<T,U>(t, fn, dst)); else u = fn.apply(t); } catch (Throwable rex) { @@ -697,11 +727,11 @@ static final class ThenAccept<T> extends Completion { final CompletableFuture<? extends T> src; final Consumer<? super T> fn; - final CompletableFuture<Void> dst; + final CompletableFuture<?> dst; final Executor executor; ThenAccept(CompletableFuture<? extends T> src, Consumer<? super T> fn, - CompletableFuture<Void> dst, + CompletableFuture<?> dst, Executor executor) { this.src = src; this.fn = fn; this.dst = dst; this.executor = executor; @@ -709,7 +739,7 @@ public final void run() { final CompletableFuture<? extends T> a; final Consumer<? super T> fn; - final CompletableFuture<Void> dst; + final CompletableFuture<?> dst; Object r; T t; Throwable ex; if ((dst = this.dst) != null && (fn = this.fn) != null && @@ -729,7 +759,7 @@ if (ex == null) { try { if (e != null) - e.execute(new AsyncAccept<T>(t, fn, dst)); + execAsync(e, new AsyncAccept<T>(t, fn, dst)); else fn.accept(t); } catch (Throwable rex) { @@ -773,7 +803,7 @@ if (ex == null) { try { if (e != null) - e.execute(new AsyncRun(fn, dst)); + execAsync(e, new AsyncRun(fn, dst)); else fn.run(); } catch (Throwable rex) { @@ -839,7 +869,7 @@ if (ex == null) { try { if (e != null) - e.execute(new AsyncCombine<T,U,V>(t, u, fn, dst)); + execAsync(e, new AsyncCombine<T,U,V>(t, u, fn, dst)); else v = fn.apply(t, u); } catch (Throwable rex) { @@ -904,7 +934,7 @@ if (ex == null) { try { if (e != null) - e.execute(new AsyncAcceptBoth<T,U>(t, u, fn, dst)); + execAsync(e, new AsyncAcceptBoth<T,U>(t, u, fn, dst)); else fn.accept(t, u); } catch (Throwable rex) { @@ -956,7 +986,7 @@ if (ex == null) { try { if (e != null) - e.execute(new AsyncRun(fn, dst)); + execAsync(e, new AsyncRun(fn, dst)); else fn.run(); } catch (Throwable rex) { @@ -1042,7 +1072,7 @@ if (ex == null) { try { if (e != null) - e.execute(new AsyncApply<T,U>(t, fn, dst)); + execAsync(e, new AsyncApply<T,U>(t, fn, dst)); else u = fn.apply(t); } catch (Throwable rex) { @@ -1095,7 +1125,7 @@ if (ex == null) { try { if (e != null) - e.execute(new AsyncAccept<T>(t, fn, dst)); + execAsync(e, new AsyncAccept<T>(t, fn, dst)); else fn.accept(t); } catch (Throwable rex) { @@ -1143,7 +1173,7 @@ if (ex == null) { try { if (e != null) - e.execute(new AsyncRun(fn, dst)); + execAsync(e, new AsyncRun(fn, dst)); else fn.run(); } catch (Throwable rex) { @@ -1226,6 +1256,54 @@ private static final long serialVersionUID = 5232453952276885070L; } + static final class WhenCompleteCompletion<T> extends Completion { + final CompletableFuture<? extends T> src; + final BiConsumer<? super T, ? super Throwable> fn; + final CompletableFuture<T> dst; + final Executor executor; + WhenCompleteCompletion(CompletableFuture<? extends T> src, + BiConsumer<? super T, ? super Throwable> fn, + CompletableFuture<T> dst, + Executor executor) { + this.src = src; this.fn = fn; this.dst = dst; + this.executor = executor; + } + public final void run() { + final CompletableFuture<? extends T> a; + final BiConsumer<? super T, ? super Throwable> fn; + final CompletableFuture<T> dst; + Object r; T t; Throwable ex; + if ((dst = this.dst) != null && + (fn = this.fn) != null && + (a = this.src) != null && + (r = a.result) != null && + compareAndSet(0, 1)) { + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + Executor e = executor; + Throwable dx = null; + try { + if (e != null) + execAsync(e, new AsyncWhenComplete<T>(t, ex, fn, dst)); + else + fn.accept(t, ex); + } catch (Throwable rex) { + dx = rex; + } + if (e == null || dx != null) + dst.internalComplete(t, ex != null ? ex : dx); + } + } + private static final long serialVersionUID = 5232453952276885070L; + } + static final class ThenCopy<T> extends Completion { final CompletableFuture<?> src; final CompletableFuture<T> dst; @@ -1286,10 +1364,13 @@ final CompletableFuture<? extends T> src; final BiFunction<? super T, Throwable, ? extends U> fn; final CompletableFuture<U> dst; + final Executor executor; HandleCompletion(CompletableFuture<? extends T> src, BiFunction<? super T, Throwable, ? extends U> fn, - CompletableFuture<U> dst) { + CompletableFuture<U> dst, + Executor executor) { this.src = src; this.fn = fn; this.dst = dst; + this.executor = executor; } public final void run() { final CompletableFuture<? extends T> a; @@ -1310,13 +1391,19 @@ @SuppressWarnings("unchecked") T tr = (T) r; t = tr; } - U u = null; Throwable dx = null; + Executor e = executor; + U u = null; + Throwable dx = null; try { - u = fn.apply(t, ex); + if (e != null) + execAsync(e, new AsyncCombine<T,Throwable,U>(t, ex, fn, dst)); + else + u = fn.apply(t, ex); } catch (Throwable rex) { dx = rex; } - dst.internalComplete(u, dx); + if (e == null || dx != null) + dst.internalComplete(u, dx); } } private static final long serialVersionUID = 5232453952276885070L; @@ -1324,11 +1411,11 @@ static final class ThenCompose<T,U> extends Completion { final CompletableFuture<? extends T> src; - final Function<? super T, CompletableFuture<U>> fn; + final Function<? super T, ? extends CompletionStage<U>> fn; final CompletableFuture<U> dst; final Executor executor; ThenCompose(CompletableFuture<? extends T> src, - Function<? super T, CompletableFuture<U>> fn, + Function<? super T, ? extends CompletionStage<U>> fn, CompletableFuture<U> dst, Executor executor) { this.src = src; this.fn = fn; this.dst = dst; @@ -1336,7 +1423,7 @@ } public final void run() { final CompletableFuture<? extends T> a; - final Function<? super T, CompletableFuture<U>> fn; + final Function<? super T, ? extends CompletionStage<U>> fn; final CompletableFuture<U> dst; Object r; T t; Throwable ex; Executor e; if ((dst = this.dst) != null && @@ -1358,10 +1445,12 @@ boolean complete = false; if (ex == null) { if ((e = executor) != null) - e.execute(new AsyncCompose<T,U>(t, fn, dst)); + execAsync(e, new AsyncCompose<T,U>(t, fn, dst)); else { try { - if ((c = fn.apply(t)) == null) + CompletionStage<U> cs = fn.apply(t); + c = (cs == null) ? null : cs.toCompletableFuture(); + if (c == null) ex = new NullPointerException(); } catch (Throwable rex) { ex = rex; @@ -1401,6 +1490,619 @@ private static final long serialVersionUID = 5232453952276885070L; } + // Implementations of stage methods with (plain, async, Executor) forms + + private <U> CompletableFuture<U> doThenApply + (Function<? super T,? extends U> fn, + Executor e) { + if (fn == null) throw new NullPointerException(); + CompletableFuture<U> dst = new CompletableFuture<U>(); + ThenApply<T,U> d = null; + Object r; + if ((r = result) == null) { + CompletionNode p = new CompletionNode + (d = new ThenApply<T,U>(this, fn, dst, e)); + while ((r = result) == null) { + if (UNSAFE.compareAndSwapObject + (this, COMPLETIONS, p.next = completions, p)) + break; + } + } + if (r != null && (d == null || d.compareAndSet(0, 1))) { + T t; Throwable ex; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + U u = null; + if (ex == null) { + try { + if (e != null) + execAsync(e, new AsyncApply<T,U>(t, fn, dst)); + else + u = fn.apply(t); + } catch (Throwable rex) { + ex = rex; + } + } + if (e == null || ex != null) + dst.internalComplete(u, ex); + } + helpPostComplete(); + return dst; + } + + private CompletableFuture<Void> doThenAccept(Consumer<? super T> fn, + Executor e) { + if (fn == null) throw new NullPointerException(); + CompletableFuture<Void> dst = new CompletableFuture<Void>(); + ThenAccept<T> d = null; + Object r; + if ((r = result) == null) { + CompletionNode p = new CompletionNode + (d = new ThenAccept<T>(this, fn, dst, e)); + while ((r = result) == null) { + if (UNSAFE.compareAndSwapObject + (this, COMPLETIONS, p.next = completions, p)) + break; + } + } + if (r != null && (d == null || d.compareAndSet(0, 1))) { + T t; Throwable ex; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + if (ex == null) { + try { + if (e != null) + execAsync(e, new AsyncAccept<T>(t, fn, dst)); + else + fn.accept(t); + } catch (Throwable rex) { + ex = rex; + } + } + if (e == null || ex != null) + dst.internalComplete(null, ex); + } + helpPostComplete(); + return dst; + } + + private CompletableFuture<Void> doThenRun(Runnable action, + Executor e) { + if (action == null) throw new NullPointerException(); + CompletableFuture<Void> dst = new CompletableFuture<Void>(); + ThenRun d = null; + Object r; + if ((r = result) == null) { + CompletionNode p = new CompletionNode + (d = new ThenRun(this, action, dst, e)); + while ((r = result) == null) { + if (UNSAFE.compareAndSwapObject + (this, COMPLETIONS, p.next = completions, p)) + break; + } + } + if (r != null && (d == null || d.compareAndSet(0, 1))) { + Throwable ex; + if (r instanceof AltResult) + ex = ((AltResult)r).ex; + else + ex = null; + if (ex == null) { + try { + if (e != null) + execAsync(e, new AsyncRun(action, dst)); + else + action.run(); + } catch (Throwable rex) { + ex = rex; + } + } + if (e == null || ex != null) + dst.internalComplete(null, ex); + } + helpPostComplete(); + return dst; + } + + private <U,V> CompletableFuture<V> doThenCombine + (CompletableFuture<? extends U> other, + BiFunction<? super T,? super U,? extends V> fn, + Executor e) { + if (other == null || fn == null) throw new NullPointerException(); + CompletableFuture<V> dst = new CompletableFuture<V>(); + ThenCombine<T,U,V> d = null; + Object r, s = null; + if ((r = result) == null || (s = other.result) == null) { + d = new ThenCombine<T,U,V>(this, other, fn, dst, e); + CompletionNode q = null, p = new CompletionNode(d); + while ((r == null && (r = result) == null) || + (s == null && (s = other.result) == null)) { + if (q != null) { + if (s != null || + UNSAFE.compareAndSwapObject + (other, COMPLETIONS, q.next = other.completions, q)) + break; + } + else if (r != null || + UNSAFE.compareAndSwapObject + (this, COMPLETIONS, p.next = completions, p)) { + if (s != null) + break; + q = new CompletionNode(d); + } + } + } + if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { + T t; U u; Throwable ex; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + if (ex != null) + u = null; + else if (s instanceof AltResult) { + ex = ((AltResult)s).ex; + u = null; + } + else { + @SuppressWarnings("unchecked") U us = (U) s; + u = us; + } + V v = null; + if (ex == null) { + try { + if (e != null) + execAsync(e, new AsyncCombine<T,U,V>(t, u, fn, dst)); + else + v = fn.apply(t, u); + } catch (Throwable rex) { + ex = rex; + } + } + if (e == null || ex != null) + dst.internalComplete(v, ex); + } + helpPostComplete(); + other.helpPostComplete(); + return dst; + } + + private <U> CompletableFuture<Void> doThenAcceptBoth + (CompletableFuture<? extends U> other, + BiConsumer<? super T,? super U> fn, + Executor e) { + if (other == null || fn == null) throw new NullPointerException(); + CompletableFuture<Void> dst = new CompletableFuture<Void>(); + ThenAcceptBoth<T,U> d = null; + Object r, s = null; + if ((r = result) == null || (s = other.result) == null) { + d = new ThenAcceptBoth<T,U>(this, other, fn, dst, e); + CompletionNode q = null, p = new CompletionNode(d); + while ((r == null && (r = result) == null) || + (s == null && (s = other.result) == null)) { + if (q != null) { + if (s != null || + UNSAFE.compareAndSwapObject + (other, COMPLETIONS, q.next = other.completions, q)) + break; + } + else if (r != null || + UNSAFE.compareAndSwapObject + (this, COMPLETIONS, p.next = completions, p)) { + if (s != null) + break; + q = new CompletionNode(d); + } + } + } + if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { + T t; U u; Throwable ex; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + if (ex != null) + u = null; + else if (s instanceof AltResult) { + ex = ((AltResult)s).ex; + u = null; + } + else { + @SuppressWarnings("unchecked") U us = (U) s; + u = us; + } + if (ex == null) { + try { + if (e != null) + execAsync(e, new AsyncAcceptBoth<T,U>(t, u, fn, dst)); + else + fn.accept(t, u); + } catch (Throwable rex) { + ex = rex; + } + } + if (e == null || ex != null) + dst.internalComplete(null, ex); + } + helpPostComplete(); + other.helpPostComplete(); + return dst; + } + + private CompletableFuture<Void> doRunAfterBoth(CompletableFuture<?> other, + Runnable action, + Executor e) { + if (other == null || action == null) throw new NullPointerException(); + CompletableFuture<Void> dst = new CompletableFuture<Void>(); + RunAfterBoth d = null; + Object r, s = null; + if ((r = result) == null || (s = other.result) == null) { + d = new RunAfterBoth(this, other, action, dst, e); + CompletionNode q = null, p = new CompletionNode(d); + while ((r == null && (r = result) == null) || + (s == null && (s = other.result) == null)) { + if (q != null) { + if (s != null || + UNSAFE.compareAndSwapObject + (other, COMPLETIONS, q.next = other.completions, q)) + break; + } + else if (r != null || + UNSAFE.compareAndSwapObject + (this, COMPLETIONS, p.next = completions, p)) { + if (s != null) + break; + q = new CompletionNode(d); + } + } + } + if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { + Throwable ex; + if (r instanceof AltResult) + ex = ((AltResult)r).ex; + else + ex = null; + if (ex == null && (s instanceof AltResult)) + ex = ((AltResult)s).ex; + if (ex == null) { + try { + if (e != null) + execAsync(e, new AsyncRun(action, dst)); + else + action.run(); + } catch (Throwable rex) { + ex = rex; + } + } + if (e == null || ex != null) + dst.internalComplete(null, ex); + } + helpPostComplete(); + other.helpPostComplete(); + return dst; + } + + private <U> CompletableFuture<U> doApplyToEither + (CompletableFuture<? extends T> other, + Function<? super T, U> fn, + Executor e) { + if (other == null || fn == null) throw new NullPointerException(); + CompletableFuture<U> dst = new CompletableFuture<U>(); + ApplyToEither<T,U> d = null; + Object r; + if ((r = result) == null && (r = other.result) == null) { + d = new ApplyToEither<T,U>(this, other, fn, dst, e); + CompletionNode q = null, p = new CompletionNode(d); + while ((r = result) == null && (r = other.result) == null) { + if (q != null) { + if (UNSAFE.compareAndSwapObject + (other, COMPLETIONS, q.next = other.completions, q)) + break; + } + else if (UNSAFE.compareAndSwapObject + (this, COMPLETIONS, p.next = completions, p)) + q = new CompletionNode(d); + } + } + if (r != null && (d == null || d.compareAndSet(0, 1))) { + T t; Throwable ex; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + U u = null; + if (ex == null) { + try { + if (e != null) + execAsync(e, new AsyncApply<T,U>(t, fn, dst)); + else + u = fn.apply(t); + } catch (Throwable rex) { + ex = rex; + } + } + if (e == null || ex != null) + dst.internalComplete(u, ex); + } + helpPostComplete(); + other.helpPostComplete(); + return dst; + } + + private CompletableFuture<Void> doAcceptEither + (CompletableFuture<? extends T> other, + Consumer<? super T> fn, + Executor e) { + if (other == null || fn == null) throw new NullPointerException(); + CompletableFuture<Void> dst = new CompletableFuture<Void>(); + AcceptEither<T> d = null; + Object r; + if ((r = result) == null && (r = other.result) == null) { + d = new AcceptEither<T>(this, other, fn, dst, e); + CompletionNode q = null, p = new CompletionNode(d); + while ((r = result) == null && (r = other.result) == null) { + if (q != null) { + if (UNSAFE.compareAndSwapObject + (other, COMPLETIONS, q.next = other.completions, q)) + break; + } + else if (UNSAFE.compareAndSwapObject + (this, COMPLETIONS, p.next = completions, p)) + q = new CompletionNode(d); + } + } + if (r != null && (d == null || d.compareAndSet(0, 1))) { + T t; Throwable ex; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + if (ex == null) { + try { + if (e != null) + execAsync(e, new AsyncAccept<T>(t, fn, dst)); + else + fn.accept(t); + } catch (Throwable rex) { + ex = rex; + } + } + if (e == null || ex != null) + dst.internalComplete(null, ex); + } + helpPostComplete(); + other.helpPostComplete(); + return dst; + } + + private CompletableFuture<Void> doRunAfterEither + (CompletableFuture<?> other, + Runnable action, + Executor e) { + if (other == null || action == null) throw new NullPointerException(); + CompletableFuture<Void> dst = new CompletableFuture<Void>(); + RunAfterEither d = null; + Object r; + if ((r = result) == null && (r = other.result) == null) { + d = new RunAfterEither(this, other, action, dst, e); + CompletionNode q = null, p = new CompletionNode(d); + while ((r = result) == null && (r = other.result) == null) { + if (q != null) { + if (UNSAFE.compareAndSwapObject + (other, COMPLETIONS, q.next = other.completions, q)) + break; + } + else if (UNSAFE.compareAndSwapObject + (this, COMPLETIONS, p.next = completions, p)) + q = new CompletionNode(d); + } + } + if (r != null && (d == null || d.compareAndSet(0, 1))) { + Throwable ex; + if (r instanceof AltResult) + ex = ((AltResult)r).ex; + else + ex = null; + if (ex == null) { + try { + if (e != null) + execAsync(e, new AsyncRun(action, dst)); + else + action.run(); + } catch (Throwable rex) { + ex = rex; + } + } + if (e == null || ex != null) + dst.internalComplete(null, ex); + } + helpPostComplete(); + other.helpPostComplete(); + return dst; + } + + private <U> CompletableFuture<U> doThenCompose + (Function<? super T, ? extends CompletionStage<U>> fn, + Executor e) { + if (fn == null) throw new NullPointerException(); + CompletableFuture<U> dst = null; + ThenCompose<T,U> d = null; + Object r; + if ((r = result) == null) { + dst = new CompletableFuture<U>(); + CompletionNode p = new CompletionNode + (d = new ThenCompose<T,U>(this, fn, dst, e)); + while ((r = result) == null) { + if (UNSAFE.compareAndSwapObject + (this, COMPLETIONS, p.next = completions, p)) + break; + } + } + if (r != null && (d == null || d.compareAndSet(0, 1))) { + T t; Throwable ex; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + if (ex == null) { + if (e != null) { + if (dst == null) + dst = new CompletableFuture<U>(); + execAsync(e, new AsyncCompose<T,U>(t, fn, dst)); + } + else { + try { + CompletionStage<U> cs = fn.apply(t); + if (cs == null || + (dst = cs.toCompletableFuture()) == null) + ex = new NullPointerException(); + } catch (Throwable rex) { + ex = rex; + } + } + } + if (dst == null) + dst = new CompletableFuture<U>(); + if (e == null || ex != null) + dst.internalComplete(null, ex); + } + helpPostComplete(); + dst.helpPostComplete(); + return dst; + } + + private CompletableFuture<T> doWhenComplete + (BiConsumer<? super T, ? super Throwable> fn, + Executor e) { + if (fn == null) throw new NullPointerException(); + CompletableFuture<T> dst = new CompletableFuture<T>(); + WhenCompleteCompletion<T> d = null; + Object r; + if ((r = result) == null) { + CompletionNode p = + new CompletionNode(d = new WhenCompleteCompletion<T> + (this, fn, dst, e)); + while ((r = result) == null) { + if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, + p.next = completions, p)) + break; + } + } + if (r != null && (d == null || d.compareAndSet(0, 1))) { + T t; Throwable ex; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + Throwable dx = null; + try { + if (e != null) + execAsync(e, new AsyncWhenComplete<T>(t, ex, fn, dst)); + else + fn.accept(t, ex); + } catch (Throwable rex) { + dx = rex; + } + if (e == null || dx != null) + dst.internalComplete(t, ex != null ? ex : dx); + } + helpPostComplete(); + return dst; + } + + private <U> CompletableFuture<U> doHandle + (BiFunction<? super T, Throwable, ? extends U> fn, + Executor e) { + if (fn == null) throw new NullPointerException(); + CompletableFuture<U> dst = new CompletableFuture<U>(); + HandleCompletion<T,U> d = null; + Object r; + if ((r = result) == null) { + CompletionNode p = + new CompletionNode(d = new HandleCompletion<T,U> + (this, fn, dst, e)); + while ((r = result) == null) { + if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, + p.next = completions, p)) + break; + } + } + if (r != null && (d == null || d.compareAndSet(0, 1))) { + T t; Throwable ex; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + U u = null; + Throwable dx = null; + try { + if (e != null) + execAsync(e, new AsyncCombine<T,Throwable,U>(t, ex, fn, dst)); + else { + u = fn.apply(t, ex); + dx = null; + } + } catch (Throwable rex) { + dx = rex; + u = null; + } + if (e == null || dx != null) + dst.internalComplete(u, dx); + } + helpPostComplete(); + return dst; + } + + // public methods /** @@ -1416,13 +2118,13 @@ * * @param supplier a function returning the value to be used * to complete the returned CompletableFuture + * @param <U> the function's return type * @return the new CompletableFuture */ public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) { if (supplier == null) throw new NullPointerException(); CompletableFuture<U> f = new CompletableFuture<U>(); - ForkJoinPool.commonPool(). - execute((ForkJoinTask<?>)new AsyncSupply<U>(supplier, f)); + execAsync(ForkJoinPool.commonPool(), new AsyncSupply<U>(supplier, f)); return f; } @@ -1434,6 +2136,7 @@ * @param supplier a function returning the value to be used * to complete the returned CompletableFuture * @param executor the executor to use for asynchronous execution + * @param <U> the function's return type * @return the new CompletableFuture */ public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, @@ -1441,7 +2144,7 @@ if (executor == null || supplier == null) throw new NullPointerException(); CompletableFuture<U> f = new CompletableFuture<U>(); - executor.execute(new AsyncSupply<U>(supplier, f)); + execAsync(executor, new AsyncSupply<U>(supplier, f)); return f; } @@ -1457,8 +2160,7 @@ public static CompletableFuture<Void> runAsync(Runnable runnable) { if (runnable == null) throw new NullPointerException(); CompletableFuture<Void> f = new CompletableFuture<Void>(); - ForkJoinPool.commonPool(). - execute((ForkJoinTask<?>)new AsyncRun(runnable, f)); + execAsync(ForkJoinPool.commonPool(), new AsyncRun(runnable, f)); return f; } @@ -1477,7 +2179,7 @@ if (executor == null || runnable == null) throw new NullPointerException(); CompletableFuture<Void> f = new CompletableFuture<Void>(); - executor.execute(new AsyncRun(runnable, f)); + execAsync(executor, new AsyncRun(runnable, f)); return f; } @@ -1486,6 +2188,7 @@ * the given value. * * @param value the value + * @param <U> the type of the value * @return the completed CompletableFuture */ public static <U> CompletableFuture<U> completedFuture(U value) { @@ -1657,60 +2360,18 @@ return triggered; } - /** - * Returns a new CompletableFuture that is completed - * when this CompletableFuture completes, with the result of the - * given function of this CompletableFuture's result. - * - * <p>If this CompletableFuture completes exceptionally, or the - * supplied function throws an exception, then the returned - * CompletableFuture completes exceptionally with a - * CompletionException holding the exception as its cause. - * - * @param fn the function to use to compute the value of - * the returned CompletableFuture - * @return the new CompletableFuture - */ - public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn) { + // CompletionStage methods + + public <U> CompletableFuture<U> thenApply + (Function<? super T,? extends U> fn) { return doThenApply(fn, null); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when this CompletableFuture completes, with the result of the - * given function of this CompletableFuture's result from a - * task running in the {@link ForkJoinPool#commonPool()}. - * - * <p>If this CompletableFuture completes exceptionally, or the - * supplied function throws an exception, then the returned - * CompletableFuture completes exceptionally with a - * CompletionException holding the exception as its cause. - * - * @param fn the function to use to compute the value of - * the returned CompletableFuture - * @return the new CompletableFuture - */ public <U> CompletableFuture<U> thenApplyAsync (Function<? super T,? extends U> fn) { return doThenApply(fn, ForkJoinPool.commonPool()); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when this CompletableFuture completes, with the result of the - * given function of this CompletableFuture's result from a - * task running in the given executor. - * - * <p>If this CompletableFuture completes exceptionally, or the - * supplied function throws an exception, then the returned - * CompletableFuture completes exceptionally with a - * CompletionException holding the exception as its cause. - * - * @param fn the function to use to compute the value of - * the returned CompletableFuture - * @param executor the executor to use for asynchronous execution - * @return the new CompletableFuture - */ public <U> CompletableFuture<U> thenApplyAsync (Function<? super T,? extends U> fn, Executor executor) { @@ -1718,1149 +2379,228 @@ return doThenApply(fn, executor); } - private <U> CompletableFuture<U> doThenApply - (Function<? super T,? extends U> fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture<U> dst = new CompletableFuture<U>(); - ThenApply<T,U> d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenApply<T,U>(this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - U u = null; - if (ex == null) { - try { - if (e != null) - e.execute(new AsyncApply<T,U>(t, fn, dst)); - else - u = fn.apply(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(u, ex); - } - helpPostComplete(); - return dst; + public CompletableFuture<Void> thenAccept + (Consumer<? super T> action) { + return doThenAccept(action, null); } - /** - * Returns a new CompletableFuture that is completed - * when this CompletableFuture completes, after performing the given - * action with this CompletableFuture's result. - * - * <p>If this CompletableFuture completes exceptionally, or the - * supplied action throws an exception, then the returned - * CompletableFuture completes exceptionally with a - * CompletionException holding the exception as its cause. - * - * @param block the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ - public CompletableFuture<Void> thenAccept(Consumer<? super T> block) { - return doThenAccept(block, null); + public CompletableFuture<Void> thenAcceptAsync + (Consumer<? super T> action) { + return doThenAccept(action, ForkJoinPool.commonPool()); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when this CompletableFuture completes, after performing the given - * action with this CompletableFuture's result from a task running - * in the {@link ForkJoinPool#commonPool()}. - * - * <p>If this CompletableFuture completes exceptionally, or the - * supplied action throws an exception, then the returned - * CompletableFuture completes exceptionally with a - * CompletionException holding the exception as its cause. - * - * @param block the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ - public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> block) { - return doThenAccept(block, ForkJoinPool.commonPool()); + public CompletableFuture<Void> thenAcceptAsync + (Consumer<? super T> action, + Executor executor) { + if (executor == null) throw new NullPointerException(); + return doThenAccept(action, executor); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when this CompletableFuture completes, after performing the given - * action with this CompletableFuture's result from a task running - * in the given executor. - * - * <p>If this CompletableFuture completes exceptionally, or the - * supplied action throws an exception, then the returned - * CompletableFuture completes exceptionally with a - * CompletionException holding the exception as its cause. - * - * @param block the action to perform before completing the - * returned CompletableFuture - * @param executor the executor to use for asynchronous execution - * @return the new CompletableFuture - */ - public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> block, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenAccept(block, executor); - } - - private CompletableFuture<Void> doThenAccept(Consumer<? super T> fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture<Void> dst = new CompletableFuture<Void>(); - ThenAccept<T> d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenAccept<T>(this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex == null) { - try { - if (e != null) - e.execute(new AsyncAccept<T>(t, fn, dst)); - else - fn.accept(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - return dst; - } - - /** - * Returns a new CompletableFuture that is completed - * when this CompletableFuture completes, after performing the given - * action. - * - * <p>If this CompletableFuture completes exceptionally, or the - * supplied action throws an exception, then the returned - * CompletableFuture completes exceptionally with a - * CompletionException holding the exception as its cause. - * - * @param action the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ - public CompletableFuture<Void> thenRun(Runnable action) { + public CompletableFuture<Void> thenRun + (Runnable action) { return doThenRun(action, null); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when this CompletableFuture completes, after performing the given - * action from a task running in the {@link ForkJoinPool#commonPool()}. - * - * <p>If this CompletableFuture completes exceptionally, or the - * supplied action throws an exception, then the returned - * CompletableFuture completes exceptionally with a - * CompletionException holding the exception as its cause. - * - * @param action the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ - public CompletableFuture<Void> thenRunAsync(Runnable action) { + public CompletableFuture<Void> thenRunAsync + (Runnable action) { return doThenRun(action, ForkJoinPool.commonPool()); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when this CompletableFuture completes, after performing the given - * action from a task running in the given executor. - * - * <p>If this CompletableFuture completes exceptionally, or the - * supplied action throws an exception, then the returned - * CompletableFuture completes exceptionally with a - * CompletionException holding the exception as its cause. - * - * @param action the action to perform before completing the - * returned CompletableFuture - * @param executor the executor to use for asynchronous execution - * @return the new CompletableFuture - */ - public CompletableFuture<Void> thenRunAsync(Runnable action, - Executor executor) { + public CompletableFuture<Void> thenRunAsync + (Runnable action, + Executor executor) { if (executor == null) throw new NullPointerException(); return doThenRun(action, executor); } - private CompletableFuture<Void> doThenRun(Runnable action, - Executor e) { - if (action == null) throw new NullPointerException(); - CompletableFuture<Void> dst = new CompletableFuture<Void>(); - ThenRun d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenRun(this, action, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null) { - try { - if (e != null) - e.execute(new AsyncRun(action, dst)); - else - action.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - return dst; + public <U,V> CompletableFuture<V> thenCombine + (CompletionStage<? extends U> other, + BiFunction<? super T,? super U,? extends V> fn) { + return doThenCombine(other.toCompletableFuture(), fn, null); } - /** - * Returns a new CompletableFuture that is completed - * when both this and the other given CompletableFuture complete, - * with the result of the given function of the results of the two - * CompletableFutures. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, or the supplied function throws an exception, - * then the returned CompletableFuture completes exceptionally - * with a CompletionException holding the exception as its cause. - * - * @param other the other CompletableFuture - * @param fn the function to use to compute the value of - * the returned CompletableFuture - * @return the new CompletableFuture - */ - public <U,V> CompletableFuture<V> thenCombine - (CompletableFuture<? extends U> other, + public <U,V> CompletableFuture<V> thenCombineAsync + (CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn) { - return doThenCombine(other, fn, null); + return doThenCombine(other.toCompletableFuture(), fn, + ForkJoinPool.commonPool()); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when both this and the other given CompletableFuture complete, - * with the result of the given function of the results of the two - * CompletableFutures from a task running in the - * {@link ForkJoinPool#commonPool()}. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, or the supplied function throws an exception, - * then the returned CompletableFuture completes exceptionally - * with a CompletionException holding the exception as its cause. - * - * @param other the other CompletableFuture - * @param fn the function to use to compute the value of - * the returned CompletableFuture - * @return the new CompletableFuture - */ public <U,V> CompletableFuture<V> thenCombineAsync - (CompletableFuture<? extends U> other, - BiFunction<? super T,? super U,? extends V> fn) { - return doThenCombine(other, fn, ForkJoinPool.commonPool()); - } - - /** - * Returns a new CompletableFuture that is asynchronously completed - * when both this and the other given CompletableFuture complete, - * with the result of the given function of the results of the two - * CompletableFutures from a task running in the given executor. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, or the supplied function throws an exception, - * then the returned CompletableFuture completes exceptionally - * with a CompletionException holding the exception as its cause. - * - * @param other the other CompletableFuture - * @param fn the function to use to compute the value of - * the returned CompletableFuture - * @param executor the executor to use for asynchronous execution - * @return the new CompletableFuture - */ - public <U,V> CompletableFuture<V> thenCombineAsync - (CompletableFuture<? extends U> other, + (CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor) { if (executor == null) throw new NullPointerException(); - return doThenCombine(other, fn, executor); + return doThenCombine(other.toCompletableFuture(), fn, executor); } - private <U,V> CompletableFuture<V> doThenCombine - (CompletableFuture<? extends U> other, - BiFunction<? super T,? super U,? extends V> fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture<V> dst = new CompletableFuture<V>(); - ThenCombine<T,U,V> d = null; - Object r, s = null; - if ((r = result) == null || (s = other.result) == null) { - d = new ThenCombine<T,U,V>(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r == null && (r = result) == null) || - (s == null && (s = other.result) == null)) { - if (q != null) { - if (s != null || - UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (r != null || - UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) { - if (s != null) - break; - q = new CompletionNode(d); - } - } - } - if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { - T t; U u; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex != null) - u = null; - else if (s instanceof AltResult) { - ex = ((AltResult)s).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - V v = null; - if (ex == null) { - try { - if (e != null) - e.execute(new AsyncCombine<T,U,V>(t, u, fn, dst)); - else - v = fn.apply(t, u); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(v, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; + public <U> CompletableFuture<Void> thenAcceptBoth + (CompletionStage<? extends U> other, + BiConsumer<? super T, ? super U> action) { + return doThenAcceptBoth(other.toCompletableFuture(), action, null); } - /** - * Returns a new CompletableFuture that is completed - * when both this and the other given CompletableFuture complete, - * after performing the given action with the results of the two - * CompletableFutures. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, or the supplied action throws an exception, - * then the returned CompletableFuture completes exceptionally - * with a CompletionException holding the exception as its cause. - * - * @param other the other CompletableFuture - * @param block the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ - public <U> CompletableFuture<Void> thenAcceptBoth - (CompletableFuture<? extends U> other, - BiConsumer<? super T, ? super U> block) { - return doThenAcceptBoth(other, block, null); + public <U> CompletableFuture<Void> thenAcceptBothAsync + (CompletionStage<? extends U> other, + BiConsumer<? super T, ? super U> action) { + return doThenAcceptBoth(other.toCompletableFuture(), action, + ForkJoinPool.commonPool()); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when both this and the other given CompletableFuture complete, - * after performing the given action with the results of the two - * CompletableFutures from a task running in the {@link - * ForkJoinPool#commonPool()}. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, or the supplied action throws an exception, - * then the returned CompletableFuture completes exceptionally - * with a CompletionException holding the exception as its cause. - * - * @param other the other CompletableFuture - * @param block the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ public <U> CompletableFuture<Void> thenAcceptBothAsync - (CompletableFuture<? extends U> other, - BiConsumer<? super T, ? super U> block) { - return doThenAcceptBoth(other, block, ForkJoinPool.commonPool()); + (CompletionStage<? extends U> other, + BiConsumer<? super T, ? super U> action, + Executor executor) { + if (executor == null) throw new NullPointerException(); + return doThenAcceptBoth(other.toCompletableFuture(), action, executor); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when both this and the other given CompletableFuture complete, - * after performing the given action with the results of the two - * CompletableFutures from a task running in the given executor. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, or the supplied action throws an exception, - * then the returned CompletableFuture completes exceptionally - * with a CompletionException holding the exception as its cause. - * - * @param other the other CompletableFuture - * @param block the action to perform before completing the - * returned CompletableFuture - * @param executor the executor to use for asynchronous execution - * @return the new CompletableFuture - */ - public <U> CompletableFuture<Void> thenAcceptBothAsync - (CompletableFuture<? extends U> other, - BiConsumer<? super T, ? super U> block, + public CompletableFuture<Void> runAfterBoth + (CompletionStage<?> other, + Runnable action) { + return doRunAfterBoth(other.toCompletableFuture(), action, null); + } + + public CompletableFuture<Void> runAfterBothAsync + (CompletionStage<?> other, + Runnable action) { + return doRunAfterBoth(other.toCompletableFuture(), action, + ForkJoinPool.commonPool()); + } + + public CompletableFuture<Void> runAfterBothAsync + (CompletionStage<?> other, + Runnable action, Executor executor) { if (executor == null) throw new NullPointerException(); - return doThenAcceptBoth(other, block, executor); + return doRunAfterBoth(other.toCompletableFuture(), action, executor); } - private <U> CompletableFuture<Void> doThenAcceptBoth - (CompletableFuture<? extends U> other, - BiConsumer<? super T,? super U> fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture<Void> dst = new CompletableFuture<Void>(); - ThenAcceptBoth<T,U> d = null; - Object r, s = null; - if ((r = result) == null || (s = other.result) == null) { - d = new ThenAcceptBoth<T,U>(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r == null && (r = result) == null) || - (s == null && (s = other.result) == null)) { - if (q != null) { - if (s != null || - UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (r != null || - UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) { - if (s != null) - break; - q = new CompletionNode(d); - } - } - } - if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { - T t; U u; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex != null) - u = null; - else if (s instanceof AltResult) { - ex = ((AltResult)s).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - if (ex == null) { - try { - if (e != null) - e.execute(new AsyncAcceptBoth<T,U>(t, u, fn, dst)); - else - fn.accept(t, u); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; + + public <U> CompletableFuture<U> applyToEither + (CompletionStage<? extends T> other, + Function<? super T, U> fn) { + return doApplyToEither(other.toCompletableFuture(), fn, null); } - /** - * Returns a new CompletableFuture that is completed - * when both this and the other given CompletableFuture complete, - * after performing the given action. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, or the supplied action throws an exception, - * then the returned CompletableFuture completes exceptionally - * with a CompletionException holding the exception as its cause. - * - * @param other the other CompletableFuture - * @param action the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ - public CompletableFuture<Void> runAfterBoth(CompletableFuture<?> other, - Runnable action) { - return doRunAfterBoth(other, action, null); + public <U> CompletableFuture<U> applyToEitherAsync + (CompletionStage<? extends T> other, + Function<? super T, U> fn) { + return doApplyToEither(other.toCompletableFuture(), fn, + ForkJoinPool.commonPool()); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when both this and the other given CompletableFuture complete, - * after performing the given action from a task running in the - * {@link ForkJoinPool#commonPool()}. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, or the supplied action throws an exception, - * then the returned CompletableFuture completes exceptionally - * with a CompletionException holding the exception as its cause. - * - * @param other the other CompletableFuture - * @param action the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ - public CompletableFuture<Void> runAfterBothAsync(CompletableFuture<?> other, - Runnable action) { - return doRunAfterBoth(other, action, ForkJoinPool.commonPool()); - } - - /** - * Returns a new CompletableFuture that is asynchronously completed - * when both this and the other given CompletableFuture complete, - * after performing the given action from a task running in the - * given executor. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, or the supplied action throws an exception, - * then the returned CompletableFuture completes exceptionally - * with a CompletionException holding the exception as its cause. - * - * @param other the other CompletableFuture - * @param action the action to perform before completing the - * returned CompletableFuture - * @param executor the executor to use for asynchronous execution - * @return the new CompletableFuture - */ - public CompletableFuture<Void> runAfterBothAsync(CompletableFuture<?> other, - Runnable action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doRunAfterBoth(other, action, executor); - } - - private CompletableFuture<Void> doRunAfterBoth(CompletableFuture<?> other, - Runnable action, - Executor e) { - if (other == null || action == null) throw new NullPointerException(); - CompletableFuture<Void> dst = new CompletableFuture<Void>(); - RunAfterBoth d = null; - Object r, s = null; - if ((r = result) == null || (s = other.result) == null) { - d = new RunAfterBoth(this, other, action, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r == null && (r = result) == null) || - (s == null && (s = other.result) == null)) { - if (q != null) { - if (s != null || - UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (r != null || - UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) { - if (s != null) - break; - q = new CompletionNode(d); - } - } - } - if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null && (s instanceof AltResult)) - ex = ((AltResult)s).ex; - if (ex == null) { - try { - if (e != null) - e.execute(new AsyncRun(action, dst)); - else - action.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; - } - - /** - * Returns a new CompletableFuture that is completed - * when either this or the other given CompletableFuture completes, - * with the result of the given function of either this or the other - * CompletableFuture's result. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do so, - * with a CompletionException holding one of these exceptions as its - * cause. No guarantees are made about which result or exception is - * used in the returned CompletableFuture. If the supplied function - * throws an exception, then the returned CompletableFuture completes - * exceptionally with a CompletionException holding the exception as - * its cause. - * - * @param other the other CompletableFuture - * @param fn the function to use to compute the value of - * the returned CompletableFuture - * @return the new CompletableFuture - */ - public <U> CompletableFuture<U> applyToEither - (CompletableFuture<? extends T> other, - Function<? super T, U> fn) { - return doApplyToEither(other, fn, null); - } - - /** - * Returns a new CompletableFuture that is asynchronously completed - * when either this or the other given CompletableFuture completes, - * with the result of the given function of either this or the other - * CompletableFuture's result from a task running in the - * {@link ForkJoinPool#commonPool()}. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do so, - * with a CompletionException holding one of these exceptions as its - * cause. No guarantees are made about which result or exception is - * used in the returned CompletableFuture. If the supplied function - * throws an exception, then the returned CompletableFuture completes - * exceptionally with a CompletionException holding the exception as - * its cause. - * - * @param other the other CompletableFuture - * @param fn the function to use to compute the value of - * the returned CompletableFuture - * @return the new CompletableFuture - */ public <U> CompletableFuture<U> applyToEitherAsync - (CompletableFuture<? extends T> other, - Function<? super T, U> fn) { - return doApplyToEither(other, fn, ForkJoinPool.commonPool()); - } - - /** - * Returns a new CompletableFuture that is asynchronously completed - * when either this or the other given CompletableFuture completes, - * with the result of the given function of either this or the other - * CompletableFuture's result from a task running in the - * given executor. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do so, - * with a CompletionException holding one of these exceptions as its - * cause. No guarantees are made about which result or exception is - * used in the returned CompletableFuture. If the supplied function - * throws an exception, then the returned CompletableFuture completes - * exceptionally with a CompletionException holding the exception as - * its cause. - * - * @param other the other CompletableFuture - * @param fn the function to use to compute the value of - * the returned CompletableFuture - * @param executor the executor to use for asynchronous execution - * @return the new CompletableFuture - */ - public <U> CompletableFuture<U> applyToEitherAsync - (CompletableFuture<? extends T> other, + (CompletionStage<? extends T> other, Function<? super T, U> fn, Executor executor) { if (executor == null) throw new NullPointerException(); - return doApplyToEither(other, fn, executor); + return doApplyToEither(other.toCompletableFuture(), fn, executor); } - private <U> CompletableFuture<U> doApplyToEither - (CompletableFuture<? extends T> other, - Function<? super T, U> fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture<U> dst = new CompletableFuture<U>(); - ApplyToEither<T,U> d = null; - Object r; - if ((r = result) == null && (r = other.result) == null) { - d = new ApplyToEither<T,U>(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r = result) == null && (r = other.result) == null) { - if (q != null) { - if (UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - q = new CompletionNode(d); - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - U u = null; - if (ex == null) { - try { - if (e != null) - e.execute(new AsyncApply<T,U>(t, fn, dst)); - else - u = fn.apply(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(u, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; + public CompletableFuture<Void> acceptEither + (CompletionStage<? extends T> other, + Consumer<? super T> action) { + return doAcceptEither(other.toCompletableFuture(), action, null); } - /** - * Returns a new CompletableFuture that is completed - * when either this or the other given CompletableFuture completes, - * after performing the given action with the result of either this - * or the other CompletableFuture's result. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do so, - * with a CompletionException holding one of these exceptions as its - * cause. No guarantees are made about which result or exception is - * used in the returned CompletableFuture. If the supplied action - * throws an exception, then the returned CompletableFuture completes - * exceptionally with a CompletionException holding the exception as - * its cause. - * - * @param other the other CompletableFuture - * @param block the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ - public CompletableFuture<Void> acceptEither - (CompletableFuture<? extends T> other, - Consumer<? super T> block) { - return doAcceptEither(other, block, null); + public CompletableFuture<Void> acceptEitherAsync + (CompletionStage<? extends T> other, + Consumer<? super T> action) { + return doAcceptEither(other.toCompletableFuture(), action, + ForkJoinPool.commonPool()); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when either this or the other given CompletableFuture completes, - * after performing the given action with the result of either this - * or the other CompletableFuture's result from a task running in - * the {@link ForkJoinPool#commonPool()}. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do so, - * with a CompletionException holding one of these exceptions as its - * cause. No guarantees are made about which result or exception is - * used in the returned CompletableFuture. If the supplied action - * throws an exception, then the returned CompletableFuture completes - * exceptionally with a CompletionException holding the exception as - * its cause. - * - * @param other the other CompletableFuture - * @param block the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ public CompletableFuture<Void> acceptEitherAsync - (CompletableFuture<? extends T> other, - Consumer<? super T> block) { - return doAcceptEither(other, block, ForkJoinPool.commonPool()); + (CompletionStage<? extends T> other, + Consumer<? super T> action, + Executor executor) { + if (executor == null) throw new NullPointerException(); + return doAcceptEither(other.toCompletableFuture(), action, executor); } - /** - * Returns a new CompletableFuture that is asynchronously completed - * when either this or the other given CompletableFuture completes, - * after performing the given action with the result of either this - * or the other CompletableFuture's result from a task running in - * the given executor. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do so, - * with a CompletionException holding one of these exceptions as its - * cause. No guarantees are made about which result or exception is - * used in the returned CompletableFuture. If the supplied action - * throws an exception, then the returned CompletableFuture completes - * exceptionally with a CompletionException holding the exception as - * its cause. - * - * @param other the other CompletableFuture - * @param block the action to perform before completing the - * returned CompletableFuture - * @param executor the executor to use for asynchronous execution - * @return the new CompletableFuture - */ - public CompletableFuture<Void> acceptEitherAsync - (CompletableFuture<? extends T> other, - Consumer<? super T> block, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doAcceptEither(other, block, executor); + public CompletableFuture<Void> runAfterEither(CompletionStage<?> other, + Runnable action) { + return doRunAfterEither(other.toCompletableFuture(), action, null); } - private CompletableFuture<Void> doAcceptEither - (CompletableFuture<? extends T> other, - Consumer<? super T> fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture<Void> dst = new CompletableFuture<Void>(); - AcceptEither<T> d = null; - Object r; - if ((r = result) == null && (r = other.result) == null) { - d = new AcceptEither<T>(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r = result) == null && (r = other.result) == null) { - if (q != null) { - if (UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - q = new CompletionNode(d); - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex == null) { - try { - if (e != null) - e.execute(new AsyncAccept<T>(t, fn, dst)); - else - fn.accept(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; + public CompletableFuture<Void> runAfterEitherAsync + (CompletionStage<?> other, + Runnable action) { + return doRunAfterEither(other.toCompletableFuture(), action, + ForkJoinPool.commonPool()); } - /** - * Returns a new CompletableFuture that is completed - * when either this or the other given CompletableFuture completes, - * after performing the given action. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do so, - * with a CompletionException holding one of these exceptions as its - * cause. No guarantees are made about which result or exception is - * used in the returned CompletableFuture. If the supplied action - * throws an exception, then the returned CompletableFuture completes - * exceptionally with a CompletionException holding the exception as - * its cause. - * - * @param other the other CompletableFuture - * @param action the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ - public CompletableFuture<Void> runAfterEither(CompletableFuture<?> other, - Runnable action) { - return doRunAfterEither(other, action, null); - } - - /** - * Returns a new CompletableFuture that is asynchronously completed - * when either this or the other given CompletableFuture completes, - * after performing the given action from a task running in the - * {@link ForkJoinPool#commonPool()}. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do so, - * with a CompletionException holding one of these exceptions as its - * cause. No guarantees are made about which result or exception is - * used in the returned CompletableFuture. If the supplied action - * throws an exception, then the returned CompletableFuture completes - * exceptionally with a CompletionException holding the exception as - * its cause. - * - * @param other the other CompletableFuture - * @param action the action to perform before completing the - * returned CompletableFuture - * @return the new CompletableFuture - */ public CompletableFuture<Void> runAfterEitherAsync - (CompletableFuture<?> other, - Runnable action) { - return doRunAfterEither(other, action, ForkJoinPool.commonPool()); - } - - /** - * Returns a new CompletableFuture that is asynchronously completed - * when either this or the other given CompletableFuture completes, - * after performing the given action from a task running in the - * given executor. - * - * <p>If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do so, - * with a CompletionException holding one of these exceptions as its - * cause. No guarantees are made about which result or exception is - * used in the returned CompletableFuture. If the supplied action - * throws an exception, then the returned CompletableFuture completes - * exceptionally with a CompletionException holding the exception as - * its cause. - * - * @param other the other CompletableFuture - * @param action the action to perform before completing the - * returned CompletableFuture - * @param executor the executor to use for asynchronous execution - * @return the new CompletableFuture - */ - public CompletableFuture<Void> runAfterEitherAsync - (CompletableFuture<?> other, + (CompletionStage<?> other, Runnable action, Executor executor) { if (executor == null) throw new NullPointerException(); - return doRunAfterEither(other, action, executor); + return doRunAfterEither(other.toCompletableFuture(), action, executor); } - private CompletableFuture<Void> doRunAfterEither - (CompletableFuture<?> other, - Runnable action, - Executor e) { - if (other == null || action == null) throw new NullPointerException(); - CompletableFuture<Void> dst = new CompletableFuture<Void>(); - RunAfterEither d = null; - Object r; - if ((r = result) == null && (r = other.result) == null) { - d = new RunAfterEither(this, other, action, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r = result) == null && (r = other.result) == null) { - if (q != null) { - if (UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - q = new CompletionNode(d); - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null) { - try { - if (e != null) - e.execute(new AsyncRun(action, dst)); - else - action.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; - } - - /** - * Returns a CompletableFuture that upon completion, has the same - * value as produced by the given function of the result of this - * CompletableFuture. - * - * <p>If this CompletableFuture completes exceptionally, then the - * returned CompletableFuture also does so, with a - * CompletionException holding this exception as its cause. - * Similarly, if the computed CompletableFuture completes - * exceptionally, then so does the returned CompletableFuture. - * - * @param fn the function returning a new CompletableFuture - * @return the CompletableFuture - */ public <U> CompletableFuture<U> thenCompose - (Function<? super T, CompletableFuture<U>> fn) { + (Function<? super T, ? extends CompletionStage<U>> fn) { return doThenCompose(fn, null); } - /** - * Returns a CompletableFuture that upon completion, has the same - * value as that produced asynchronously using the {@link - * ForkJoinPool#commonPool()} by the given function of the result - * of this CompletableFuture. - * - * <p>If this CompletableFuture completes exceptionally, then the - * returned CompletableFuture also does so, with a - * CompletionException holding this exception as its cause. - * Similarly, if the computed CompletableFuture completes - * exceptionally, then so does the returned CompletableFuture. - * - * @param fn the function returning a new CompletableFuture - * @return the CompletableFuture - */ public <U> CompletableFuture<U> thenComposeAsync - (Function<? super T, CompletableFuture<U>> fn) { + (Function<? super T, ? extends CompletionStage<U>> fn) { return doThenCompose(fn, ForkJoinPool.commonPool()); } - /** - * Returns a CompletableFuture that upon completion, has the same - * value as that produced asynchronously using the given executor - * by the given function of this CompletableFuture. - * - * <p>If this CompletableFuture completes exceptionally, then the - * returned CompletableFuture also does so, with a - * CompletionException holding this exception as its cause. - * Similarly, if the computed CompletableFuture completes - * exceptionally, then so does the returned CompletableFuture. - * - * @param fn the function returning a new CompletableFuture - * @param executor the executor to use for asynchronous execution - * @return the CompletableFuture - */ public <U> CompletableFuture<U> thenComposeAsync - (Function<? super T, CompletableFuture<U>> fn, + (Function<? super T, ? extends CompletionStage<U>> fn, Executor executor) { if (executor == null) throw new NullPointerException(); return doThenCompose(fn, executor); } - private <U> CompletableFuture<U> doThenCompose - (Function<? super T, CompletableFuture<U>> fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture<U> dst = null; - ThenCompose<T,U> d = null; - Object r; - if ((r = result) == null) { - dst = new CompletableFuture<U>(); - CompletionNode p = new CompletionNode - (d = new ThenCompose<T,U>(this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex == null) { - if (e != null) { - if (dst == null) - dst = new CompletableFuture<U>(); - e.execute(new AsyncCompose<T,U>(t, fn, dst)); - } - else { - try { - if ((dst = fn.apply(t)) == null) - ex = new NullPointerException(); - } catch (Throwable rex) { - ex = rex; - } - } - } - if (dst == null) - dst = new CompletableFuture<U>(); - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - dst.helpPostComplete(); - return dst; + public CompletableFuture<T> whenComplete + (BiConsumer<? super T, ? super Throwable> action) { + return doWhenComplete(action, null); } + public CompletableFuture<T> whenCompleteAsync + (BiConsumer<? super T, ? super Throwable> action) { + return doWhenComplete(action, ForkJoinPool.commonPool()); + } + + public CompletableFuture<T> whenCompleteAsync + (BiConsumer<? super T, ? super Throwable> action, + Executor executor) { + if (executor == null) throw new NullPointerException(); + return doWhenComplete(action, executor); + } + + public <U> CompletableFuture<U> handle + (BiFunction<? super T, Throwable, ? extends U> fn) { + return doHandle(fn, null); + } + + public <U> CompletableFuture<U> handleAsync + (BiFunction<? super T, Throwable, ? extends U> fn) { + return doHandle(fn, ForkJoinPool.commonPool()); + } + + public <U> CompletableFuture<U> handleAsync + (BiFunction<? super T, Throwable, ? extends U> fn, + Executor executor) { + if (executor == null) throw new NullPointerException(); + return doHandle(fn, executor); + } + + /** + * Returns this CompletableFuture + * + * @return this CompletableFuture + */ + public CompletableFuture<T> toCompletableFuture() { + return this; + } + + // not in interface CompletionStage + /** * Returns a new CompletableFuture that is completed when this * CompletableFuture completes, with the result of the given @@ -2868,6 +2608,8 @@ * completion when it completes exceptionally; otherwise, if this * CompletableFuture completes normally, then the returned * CompletableFuture also completes normally with the same value. + * Note: More flexible versions of this functionality are + * available using methods {@code whenComplete} and {@code handle}. * * @param fn the function to use to compute the value of the * returned CompletableFuture if this CompletableFuture completed @@ -2882,7 +2624,8 @@ Object r; if ((r = result) == null) { CompletionNode p = - new CompletionNode(d = new ExceptionCompletion<T>(this, fn, dst)); + new CompletionNode(d = new ExceptionCompletion<T> + (this, fn, dst)); while ((r = result) == null) { if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, p.next = completions, p)) @@ -2910,59 +2653,6 @@ return dst; } - /** - * Returns a new CompletableFuture that is completed when this - * CompletableFuture completes, with the result of the given - * function of the result and exception of this CompletableFuture's - * completion. The given function is invoked with the result (or - * {@code null} if none) and the exception (or {@code null} if none) - * of this CompletableFuture when complete. - * - * @param fn the function to use to compute the value of the - * returned CompletableFuture - * @return the new CompletableFuture - */ - public <U> CompletableFuture<U> handle - (BiFunction<? super T, Throwable, ? extends U> fn) { - if (fn == null) throw new NullPointerException(); - CompletableFuture<U> dst = new CompletableFuture<U>(); - HandleCompletion<T,U> d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = - new CompletionNode(d = new HandleCompletion<T,U>(this, fn, dst)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, - p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - U u; Throwable dx; - try { - u = fn.apply(t, ex); - dx = null; - } catch (Throwable rex) { - dx = rex; - u = null; - } - dst.internalComplete(u, dx); - } - helpPostComplete(); - return dst; - } - - /* ------------- Arbitrary-arity constructions -------------- */ /* @@ -3215,6 +2905,21 @@ } /** + * Returns {@code true} if this CompletableFuture completed + * exceptionally, in any way. Possible causes include + * cancellation, explicit invocation of {@code + * completeExceptionally}, and abrupt termination of a + * CompletionStage action. + * + * @return {@code true} if this CompletableFuture completed + * exceptionally + */ + public boolean isCompletedExceptionally() { + Object r; + return ((r = result) instanceof AltResult) && r != NIL; + } + + /** * Forcibly sets or resets the value subsequently returned by * method {@link #get()} and related methods, whether or not * already completed. This method is designed for use only in
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/util/concurrent/CompletionStage.java Wed Aug 07 19:56:20 2013 -0700 @@ -0,0 +1,760 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent; +import java.util.function.Supplier; +import java.util.function.Consumer; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.BiFunction; +import java.util.concurrent.Executor; + +/** + * A stage of a possibly asynchronous computation, that performs an + * action or computes a value when another CompletionStage completes. + * A stage completes upon termination of its computation, but this may + * in turn trigger other dependent stages. The functionality defined + * in this interface takes only a few basic forms, which expand out to + * a larger set of methods to capture a range of usage styles: <ul> + * + * <li>The computation performed by a stage may be expressed as a + * Function, Consumer, or Runnable (using methods with names including + * <em>apply</em>, <em>accept</em>, or <em>run</em>, respectively) + * depending on whether it requires arguments and/or produces results. + * For example, {@code stage.thenApply(x -> square(x)).thenAccept(x -> + * System.out.print(x)).thenRun(() -> System.out.println())}. An + * additional form (<em>compose</em>) applies functions of stages + * themselves, rather than their results. </li> + * + * <li> One stage's execution may be triggered by completion of a + * single stage, or both of two stages, or either of two stages. + * Dependencies on a single stage are arranged using methods with + * prefix <em>then</em>. Those triggered by completion of + * <em>both</em> of two stages may <em>combine</em> their results or + * effects, using correspondingly named methods. Those triggered by + * <em>either</em> of two stages make no guarantees about which of the + * results or effects are used for the dependent stage's + * computation.</li> + * + * <li> Dependencies among stages control the triggering of + * computations, but do not otherwise guarantee any particular + * ordering. Additionally, execution of a new stage's computations may + * be arranged in any of three ways: default execution, default + * asynchronous execution (using methods with suffix <em>async</em> + * that employ the stage's default asynchronous execution facility), + * or custom (via a supplied {@link Executor}). The execution + * properties of default and async modes are specified by + * CompletionStage implementations, not this interface. Methods with + * explicit Executor arguments may have arbitrary execution + * properties, and might not even support concurrent execution, but + * are arranged for processing in a way that accommodates asynchrony. + * + * <li> Two method forms support processing whether the triggering + * stage completed normally or exceptionally: Method {@link + * #whenComplete whenComplete} allows injection of an action + * regardless of outcome, otherwise preserving the outcome in its + * completion. Method {@link #handle handle} additionally allows the + * stage to compute a replacement result that may enable further + * processing by other dependent stages. In all other cases, if a + * stage's computation terminates abruptly with an (unchecked) + * exception or error, then all dependent stages requiring its + * completion complete exceptionally as well, with a {@link + * CompletionException} holding the exception as its cause. If a + * stage is dependent on <em>both</em> of two stages, and both + * complete exceptionally, then the CompletionException may correspond + * to either one of these exceptions. If a stage is dependent on + * <em>either</em> of two others, and only one of them completes + * exceptionally, no guarantees are made about whether the dependent + * stage completes normally or exceptionally. In the case of method + * {@code whenComplete}, when the supplied action itself encounters an + * exception, then the stage exceptionally completes with this + * exception if not already completed exceptionally.</li> + * + * </ul> + * + * <p>All methods adhere to the above triggering, execution, and + * exceptional completion specifications (which are not repeated in + * individual method specifications). Additionally, while arguments + * used to pass a completion result (that is, for parameters of type + * {@code T}) for methods accepting them may be null, passing a null + * value for any other parameter will result in a {@link + * NullPointerException} being thrown. + * + * <p>This interface does not define methods for initially creating, + * forcibly completing normally or exceptionally, probing completion + * status or results, or awaiting completion of a stage. + * Implementations of CompletionStage may provide means of achieving + * such effects, as appropriate. Method {@link #toCompletableFuture} + * enables interoperability among different implementations of this + * interface by providing a common conversion type. + * + * @author Doug Lea + * @since 1.8 + */ +public interface CompletionStage<T> { + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, is executed with this stage's result as the argument + * to the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param fn the function to use to compute the value of + * the returned CompletionStage + * @param <U> the function's return type + * @return the new CompletionStage + */ + public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn); + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, is executed using this stage's default asynchronous + * execution facility, with this stage's result as the argument to + * the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param fn the function to use to compute the value of + * the returned CompletionStage + * @param <U> the function's return type + * @return the new CompletionStage + */ + public <U> CompletionStage<U> thenApplyAsync + (Function<? super T,? extends U> fn); + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, is executed using the supplied Executor, with this + * stage's result as the argument to the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param fn the function to use to compute the value of + * the returned CompletionStage + * @param executor the executor to use for asynchronous execution + * @param <U> the function's return type + * @return the new CompletionStage + */ + public <U> CompletionStage<U> thenApplyAsync + (Function<? super T,? extends U> fn, + Executor executor); + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, is executed with this stage's result as the argument + * to the supplied action. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param action the action to perform before completing the + * returned CompletionStage + * @return the new CompletionStage + */ + public CompletionStage<Void> thenAccept(Consumer<? super T> action); + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, is executed using this stage's default asynchronous + * execution facility, with this stage's result as the argument to + * the supplied action. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param action the action to perform before completing the + * returned CompletionStage + * @return the new CompletionStage + */ + public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action); + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, is executed using the supplied Executor, with this + * stage's result as the argument to the supplied action. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param action the action to perform before completing the + * returned CompletionStage + * @param executor the executor to use for asynchronous execution + * @return the new CompletionStage + */ + public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action, + Executor executor); + /** + * Returns a new CompletionStage that, when this stage completes + * normally, executes the given action. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param action the action to perform before completing the + * returned CompletionStage + * @return the new CompletionStage + */ + public CompletionStage<Void> thenRun(Runnable action); + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, executes the given action using this stage's default + * asynchronous execution facility. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param action the action to perform before completing the + * returned CompletionStage + * @return the new CompletionStage + */ + public CompletionStage<Void> thenRunAsync(Runnable action); + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, executes the given action using the supplied Executor. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param action the action to perform before completing the + * returned CompletionStage + * @param executor the executor to use for asynchronous execution + * @return the new CompletionStage + */ + public CompletionStage<Void> thenRunAsync(Runnable action, + Executor executor); + + /** + * Returns a new CompletionStage that, when this and the other + * given stage both complete normally, is executed with the two + * results as arguments to the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param fn the function to use to compute the value of + * the returned CompletionStage + * @param <U> the type of the other CompletionStage's result + * @param <V> the function's return type + * @return the new CompletionStage + */ + public <U,V> CompletionStage<V> thenCombine + (CompletionStage<? extends U> other, + BiFunction<? super T,? super U,? extends V> fn); + + /** + * Returns a new CompletionStage that, when this and the other + * given stage complete normally, is executed using this stage's + * default asynchronous execution facility, with the two results + * as arguments to the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param fn the function to use to compute the value of + * the returned CompletionStage + * @param <U> the type of the other CompletionStage's result + * @param <V> the function's return type + * @return the new CompletionStage + */ + public <U,V> CompletionStage<V> thenCombineAsync + (CompletionStage<? extends U> other, + BiFunction<? super T,? super U,? extends V> fn); + + /** + * Returns a new CompletionStage that, when this and the other + * given stage complete normally, is executed using the supplied + * executor, with the two results as arguments to the supplied + * function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param fn the function to use to compute the value of + * the returned CompletionStage + * @param executor the executor to use for asynchronous execution + * @param <U> the type of the other CompletionStage's result + * @param <V> the function's return type + * @return the new CompletionStage + */ + public <U,V> CompletionStage<V> thenCombineAsync + (CompletionStage<? extends U> other, + BiFunction<? super T,? super U,? extends V> fn, + Executor executor); + + /** + * Returns a new CompletionStage that, when this and the other + * given stage both complete normally, is executed with the two + * results as arguments to the supplied action. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @param <U> the type of the other CompletionStage's result + * @return the new CompletionStage + */ + public <U> CompletionStage<Void> thenAcceptBoth + (CompletionStage<? extends U> other, + BiConsumer<? super T, ? super U> action); + + /** + * Returns a new CompletionStage that, when this and the other + * given stage complete normally, is executed using this stage's + * default asynchronous execution facility, with the two results + * as arguments to the supplied action. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @param <U> the type of the other CompletionStage's result + * @return the new CompletionStage + */ + public <U> CompletionStage<Void> thenAcceptBothAsync + (CompletionStage<? extends U> other, + BiConsumer<? super T, ? super U> action); + + /** + * Returns a new CompletionStage that, when this and the other + * given stage complete normally, is executed using the supplied + * executor, with the two results as arguments to the supplied + * function. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @param executor the executor to use for asynchronous execution + * @param <U> the type of the other CompletionStage's result + * @return the new CompletionStage + */ + public <U> CompletionStage<Void> thenAcceptBothAsync + (CompletionStage<? extends U> other, + BiConsumer<? super T, ? super U> action, + Executor executor); + + /** + * Returns a new CompletionStage that, when this and the other + * given stage both complete normally, executes the given action. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @return the new CompletionStage + */ + public CompletionStage<Void> runAfterBoth(CompletionStage<?> other, + Runnable action); + /** + * Returns a new CompletionStage that, when this and the other + * given stage complete normally, executes the given action using + * this stage's default asynchronous execution facility. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @return the new CompletionStage + */ + public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other, + Runnable action); + + /** + * Returns a new CompletionStage that, when this and the other + * given stage complete normally, executes the given action using + * the supplied executor + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @param executor the executor to use for asynchronous execution + * @return the new CompletionStage + */ + public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other, + Runnable action, + Executor executor); + /** + * Returns a new CompletionStage that, when either this or the + * other given stage complete normally, is executed with the + * corresponding result as argument to the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param fn the function to use to compute the value of + * the returned CompletionStage + * @param <U> the function's return type + * @return the new CompletionStage + */ + public <U> CompletionStage<U> applyToEither + (CompletionStage<? extends T> other, + Function<? super T, U> fn); + + /** + * Returns a new CompletionStage that, when either this or the + * other given stage complete normally, is executed using this + * stage's default asynchronous execution facility, with the + * corresponding result as argument to the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param fn the function to use to compute the value of + * the returned CompletionStage + * @param <U> the function's return type + * @return the new CompletionStage + */ + public <U> CompletionStage<U> applyToEitherAsync + (CompletionStage<? extends T> other, + Function<? super T, U> fn); + + /** + * Returns a new CompletionStage that, when either this or the + * other given stage complete normally, is executed using the + * supplied executor, with the corresponding result as argument to + * the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param fn the function to use to compute the value of + * the returned CompletionStage + * @param executor the executor to use for asynchronous execution + * @param <U> the function's return type + * @return the new CompletionStage + */ + public <U> CompletionStage<U> applyToEitherAsync + (CompletionStage<? extends T> other, + Function<? super T, U> fn, + Executor executor); + + /** + * Returns a new CompletionStage that, when either this or the + * other given stage complete normally, is executed with the + * corresponding result as argument to the supplied action. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @return the new CompletionStage + */ + public CompletionStage<Void> acceptEither + (CompletionStage<? extends T> other, + Consumer<? super T> action); + + /** + * Returns a new CompletionStage that, when either this or the + * other given stage complete normally, is executed using this + * stage's default asynchronous execution facility, with the + * corresponding result as argument to the supplied action. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @return the new CompletionStage + */ + public CompletionStage<Void> acceptEitherAsync + (CompletionStage<? extends T> other, + Consumer<? super T> action); + + /** + * Returns a new CompletionStage that, when either this or the + * other given stage complete normally, is executed using the + * supplied executor, with the corresponding result as argument to + * the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @param executor the executor to use for asynchronous execution + * @return the new CompletionStage + */ + public CompletionStage<Void> acceptEitherAsync + (CompletionStage<? extends T> other, + Consumer<? super T> action, + Executor executor); + + /** + * Returns a new CompletionStage that, when either this or the + * other given stage complete normally, executes the given action. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @return the new CompletionStage + */ + public CompletionStage<Void> runAfterEither(CompletionStage<?> other, + Runnable action); + + /** + * Returns a new CompletionStage that, when either this or the + * other given stage complete normally, executes the given action + * using this stage's default asynchronous execution facility. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @return the new CompletionStage + */ + public CompletionStage<Void> runAfterEitherAsync + (CompletionStage<?> other, + Runnable action); + + /** + * Returns a new CompletionStage that, when either this or the + * other given stage complete normally, executes the given action + * using supplied executor. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param other the other CompletionStage + * @param action the action to perform before completing the + * returned CompletionStage + * @param executor the executor to use for asynchronous execution + * @return the new CompletionStage + */ + public CompletionStage<Void> runAfterEitherAsync + (CompletionStage<?> other, + Runnable action, + Executor executor); + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, is executed with this stage as the argument + * to the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param fn the function returning a new CompletionStage + * @param <U> the type of the returned CompletionStage's result + * @return the CompletionStage + */ + public <U> CompletionStage<U> thenCompose + (Function<? super T, ? extends CompletionStage<U>> fn); + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, is executed using this stage's default asynchronous + * execution facility, with this stage as the argument to the + * supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param fn the function returning a new CompletionStage + * @param <U> the type of the returned CompletionStage's result + * @return the CompletionStage + */ + public <U> CompletionStage<U> thenComposeAsync + (Function<? super T, ? extends CompletionStage<U>> fn); + + /** + * Returns a new CompletionStage that, when this stage completes + * normally, is executed using the supplied Executor, with this + * stage's result as the argument to the supplied function. + * + * See the {@link CompletionStage} documentation for rules + * covering exceptional completion. + * + * @param fn the function returning a new CompletionStage + * @param executor the executor to use for asynchronous execution + * @param <U> the type of the returned CompletionStage's result + * @return the CompletionStage + */ + public <U> CompletionStage<U> thenComposeAsync + (Function<? super T, ? extends CompletionStage<U>> fn, + Executor executor); + + /** + * Returns a new CompletionStage that, when this stage completes + * exceptionally, is executed with this stage's exception as the + * argument to the supplied function. Otherwise, if this stage + * completes normally, then the returned stage also completes + * normally with the same value. + * + * @param fn the function to use to compute the value of the + * returned CompletionStage if this CompletionStage completed + * exceptionally + * @return the new CompletionStage + */ + public CompletionStage<T> exceptionally + (Function<Throwable, ? extends T> fn); + + /** + * Returns a new CompletionStage with the same result or exception + * as this stage, and when this stage completes, executes the + * given action with the result (or {@code null} if none) and the + * exception (or {@code null} if none) of this stage. + * + * @param action the action to perform + * @return the new CompletionStage + */ + public CompletionStage<T> whenComplete + (BiConsumer<? super T, ? super Throwable> action); + + /** + * Returns a new CompletionStage with the same result or exception + * as this stage, and when this stage completes, executes the + * given action executes the given action using this stage's + * default asynchronous execution facility, with the result (or + * {@code null} if none) and the exception (or {@code null} if + * none) of this stage as arguments. + * + * @param action the action to perform + * @return the new CompletionStage + */ + public CompletionStage<T> whenCompleteAsync + (BiConsumer<? super T, ? super Throwable> action); + + /** + * Returns a new CompletionStage with the same result or exception + * as this stage, and when this stage completes, executes using + * the supplied Executor, the given action with the result (or + * {@code null} if none) and the exception (or {@code null} if + * none) of this stage as arguments. + * + * @param action the action to perform + * @param executor the executor to use for asynchronous execution + * @return the new CompletionStage + */ + public CompletionStage<T> whenCompleteAsync + (BiConsumer<? super T, ? super Throwable> action, + Executor executor); + + /** + * Returns a new CompletionStage that, when this stage completes + * either normally or exceptionally, is executed with this stage's + * result and exception as arguments to the supplied function. + * The given function is invoked with the result (or {@code null} + * if none) and the exception (or {@code null} if none) of this + * stage when complete as arguments. + * + * @param fn the function to use to compute the value of the + * returned CompletionStage + * @param <U> the function's return type + * @return the new CompletionStage + */ + public <U> CompletionStage<U> handle + (BiFunction<? super T, Throwable, ? extends U> fn); + + /** + * Returns a new CompletionStage that, when this stage completes + * either normally or exceptionally, is executed using this stage's + * default asynchronous execution facility, with this stage's + * result and exception as arguments to the supplied function. + * The given function is invoked with the result (or {@code null} + * if none) and the exception (or {@code null} if none) of this + * stage when complete as arguments. + * + * @param fn the function to use to compute the value of the + * returned CompletionStage + * @param <U> the function's return type + * @return the new CompletionStage + */ + public <U> CompletionStage<U> handleAsync + (BiFunction<? super T, Throwable, ? extends U> fn); + + /** + * Returns a new CompletionStage that, when this stage completes + * either normally or exceptionally, is executed using the + * supplied executor, with this stage's result and exception as + * arguments to the supplied function. The given function is + * invoked with the result (or {@code null} if none) and the + * exception (or {@code null} if none) of this stage when complete + * as arguments. + * + * @param fn the function to use to compute the value of the + * returned CompletionStage + * @param executor the executor to use for asynchronous execution + * @param <U> the function's return type + * @return the new CompletionStage + */ + public <U> CompletionStage<U> handleAsync + (BiFunction<? super T, Throwable, ? extends U> fn, + Executor executor); + + /** + * Returns a {@link CompletableFuture} maintaining the same + * completion properties as this stage. If this stage is already a + * CompletableFuture, this method may return this stage itself. + * Otherwise, invocation of this method may be equivalent in + * effect to {@code thenApply(x -> x)}, but returning an instance + * of type {@code CompletableFuture}. A CompletionStage + * implementation that does not choose to interoperate with others + * may throw {@code UnsupportedOperationException}. + * + * @return the CompletableFuture + * @throws UnsupportedOperationException if this implementation + * does not interoperate with CompletableFuture + */ + public CompletableFuture<T> toCompletableFuture(); + +}
--- a/src/share/classes/java/util/logging/XMLFormatter.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/logging/XMLFormatter.java Wed Aug 07 19:56:20 2013 -0700 @@ -47,7 +47,7 @@ private LogManager manager = LogManager.getLogManager(); // Append a two digit number. - private void a2(StringBuffer sb, int x) { + private void a2(StringBuilder sb, int x) { if (x < 10) { sb.append('0'); } @@ -55,25 +55,26 @@ } // Append the time and date in ISO 8601 format - private void appendISO8601(StringBuffer sb, long millis) { - Date date = new Date(millis); - sb.append(date.getYear() + 1900); + private void appendISO8601(StringBuilder sb, long millis) { + GregorianCalendar cal = new GregorianCalendar(); + cal.setTimeInMillis(millis); + sb.append(cal.get(Calendar.YEAR) + 1900); sb.append('-'); - a2(sb, date.getMonth() + 1); + a2(sb, cal.get(Calendar.MONTH) + 1); sb.append('-'); - a2(sb, date.getDate()); + a2(sb, cal.get(Calendar.DAY_OF_MONTH)); sb.append('T'); - a2(sb, date.getHours()); + a2(sb, cal.get(Calendar.HOUR_OF_DAY)); sb.append(':'); - a2(sb, date.getMinutes()); + a2(sb, cal.get(Calendar.MINUTE)); sb.append(':'); - a2(sb, date.getSeconds()); + a2(sb, cal.get(Calendar.SECOND)); } - // Append to the given StringBuffer an escaped version of the + // Append to the given StringBuilder an escaped version of the // given text string where XML special characters have been escaped. // For a null string we append "<null>" - private void escape(StringBuffer sb, String text) { + private void escape(StringBuilder sb, String text) { if (text == null) { text = "<null>"; } @@ -102,7 +103,7 @@ * @return a formatted log record */ public String format(LogRecord record) { - StringBuffer sb = new StringBuffer(500); + StringBuilder sb = new StringBuilder(500); sb.append("<record>\n"); sb.append(" <date>"); @@ -224,7 +225,7 @@ * @return a valid XML string */ public String getHead(Handler h) { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); String encoding; sb.append("<?xml version=\"1.0\"");
--- a/src/share/classes/java/util/stream/AbstractPipeline.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/AbstractPipeline.java Wed Aug 07 19:56:20 2013 -0700 @@ -75,11 +75,13 @@ * Backlink to the head of the pipeline chain (self if this is the source * stage). */ + @SuppressWarnings("rawtypes") private final AbstractPipeline sourceStage; /** * The "upstream" pipeline, or null if this is the source stage. */ + @SuppressWarnings("rawtypes") private final AbstractPipeline previousStage; /** @@ -92,6 +94,7 @@ * The next stage in the pipeline, or null if this is the last stage. * Effectively final at the point of linking to the next pipeline. */ + @SuppressWarnings("rawtypes") private AbstractPipeline nextStage; /** @@ -222,8 +225,8 @@ linkedOrConsumed = true; return isParallel() - ? (R) terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags())) - : (R) terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags())); + ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags())) + : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags())); } /** @@ -232,6 +235,7 @@ * @param generator the array generator to be used to create array instances * @return a flat array-backed Node that holds the collected output elements */ + @SuppressWarnings("unchecked") final Node<E_OUT> evaluateToArrayNode(IntFunction<E_OUT[]> generator) { if (linkedOrConsumed) throw new IllegalStateException("stream has already been operated upon"); @@ -256,6 +260,7 @@ * @throws IllegalStateException if this pipeline stage is not the source * stage. */ + @SuppressWarnings("unchecked") final Spliterator<E_OUT> sourceStageSpliterator() { if (this != sourceStage) throw new IllegalStateException(); @@ -265,11 +270,13 @@ linkedOrConsumed = true; if (sourceStage.sourceSpliterator != null) { + @SuppressWarnings("unchecked") Spliterator<E_OUT> s = sourceStage.sourceSpliterator; sourceStage.sourceSpliterator = null; return s; } else if (sourceStage.sourceSupplier != null) { + @SuppressWarnings("unchecked") Spliterator<E_OUT> s = (Spliterator<E_OUT>) sourceStage.sourceSupplier.get(); sourceStage.sourceSupplier = null; return s; @@ -282,12 +289,14 @@ // BaseStream @Override + @SuppressWarnings("unchecked") public final S sequential() { sourceStage.parallel = false; return (S) this; } @Override + @SuppressWarnings("unchecked") public final S parallel() { sourceStage.parallel = true; return (S) this; @@ -295,6 +304,7 @@ // Primitive specialization use co-variant overrides, hence is not final @Override + @SuppressWarnings("unchecked") public Spliterator<E_OUT> spliterator() { if (linkedOrConsumed) throw new IllegalStateException("stream has already been operated upon"); @@ -302,12 +312,14 @@ if (this == sourceStage) { if (sourceStage.sourceSpliterator != null) { - Spliterator<E_OUT> s = sourceStage.sourceSpliterator; + @SuppressWarnings("unchecked") + Spliterator<E_OUT> s = (Spliterator<E_OUT>) sourceStage.sourceSpliterator; sourceStage.sourceSpliterator = null; return s; } else if (sourceStage.sourceSupplier != null) { - Supplier<Spliterator<E_OUT>> s = sourceStage.sourceSupplier; + @SuppressWarnings("unchecked") + Supplier<Spliterator<E_OUT>> s = (Supplier<Spliterator<E_OUT>>) sourceStage.sourceSupplier; sourceStage.sourceSupplier = null; return lazySpliterator(s); } @@ -349,10 +361,11 @@ * @param terminalFlags Operation flags for the terminal operation */ private void parallelPrepare(int terminalFlags) { + @SuppressWarnings("rawtypes") AbstractPipeline backPropagationHead = sourceStage; if (sourceStage.sourceAnyStateful) { int depth = 1; - for (AbstractPipeline u = sourceStage, p = sourceStage.nextStage; + for ( @SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage; p != null; u = p, p = p.nextStage) { int thisOpFlags = p.sourceOrOpFlags; @@ -383,7 +396,7 @@ // Apply the upstream terminal flags if (terminalFlags != 0) { int upstreamTerminalFlags = terminalFlags & StreamOpFlag.UPSTREAM_TERMINAL_OP_MASK; - for (AbstractPipeline p = backPropagationHead; p.nextStage != null; p = p.nextStage) { + for ( @SuppressWarnings("rawtypes") AbstractPipeline p = backPropagationHead; p.nextStage != null; p = p.nextStage) { p.combinedFlags = StreamOpFlag.combineOpFlags(upstreamTerminalFlags, p.combinedFlags); } @@ -398,6 +411,7 @@ * of all computations up to and including the most recent stateful * operation. */ + @SuppressWarnings("unchecked") private Spliterator<?> sourceSpliterator(int terminalFlags) { // Get the source spliterator of the pipeline Spliterator<?> spliterator = null; @@ -421,7 +435,7 @@ // Adapt the source spliterator, evaluating each stateful op // in the pipeline up to and including this pipeline stage - for (AbstractPipeline u = sourceStage, p = sourceStage.nextStage, e = this; + for ( @SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage, e = this; u != e; u = p, p = p.nextStage) { @@ -442,6 +456,7 @@ @Override final StreamShape getSourceShape() { + @SuppressWarnings("rawtypes") AbstractPipeline p = AbstractPipeline.this; while (p.depth > 0) { p = p.previousStage; @@ -475,7 +490,9 @@ } @Override + @SuppressWarnings("unchecked") final <P_IN> void copyIntoWithCancel(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) { + @SuppressWarnings({"rawtypes","unchecked"}) AbstractPipeline p = AbstractPipeline.this; while (p.depth > 0) { p = p.previousStage; @@ -495,16 +512,18 @@ } @Override + @SuppressWarnings("unchecked") final <P_IN> Sink<P_IN> wrapSink(Sink<E_OUT> sink) { Objects.requireNonNull(sink); - for (AbstractPipeline p=AbstractPipeline.this; p.depth > 0; p=p.previousStage) { + for ( @SuppressWarnings("rawtypes") AbstractPipeline p=AbstractPipeline.this; p.depth > 0; p=p.previousStage) { sink = p.opWrapSink(p.previousStage.combinedFlags, sink); } return (Sink<P_IN>) sink; } @Override + @SuppressWarnings("unchecked") final <P_IN> Spliterator<E_OUT> wrapSpliterator(Spliterator<P_IN> sourceSpliterator) { if (depth == 0) { return (Spliterator<E_OUT>) sourceSpliterator; @@ -591,16 +610,19 @@ /** * Make a node builder compatible with this stream shape. * - * @param exactSizeIfKnown if {@literal >=0}, then a node builder will be created that - * has a fixed capacity of at most sizeIfKnown elements. If {@literal < 0}, - * then the node builder has an unfixed capacity. A fixed capacity node - * builder will throw exceptions if an element is added after builder has - * reached capacity, or is built before the builder has reached capacity. + * @param exactSizeIfKnown if {@literal >=0}, then a node builder will be + * created that has a fixed capacity of at most sizeIfKnown elements. If + * {@literal < 0}, then the node builder has an unfixed capacity. A fixed + * capacity node builder will throw exceptions if an element is added after + * builder has reached capacity, or is built before the builder has reached + * capacity. + * * @param generator the array generator to be used to create instances of a * T[] array. For implementations supporting primitive nodes, this parameter * may be ignored. * @return a node builder */ + @Override abstract Node.Builder<E_OUT> makeNodeBuilder(long exactSizeIfKnown, IntFunction<E_OUT[]> generator); @@ -679,6 +701,7 @@ * @param spliterator the source {@code Spliterator} * @return a {@code Spliterator} describing the result of the evaluation */ + @SuppressWarnings("unchecked") <P_IN> Spliterator<E_OUT> opEvaluateParallelLazy(PipelineHelper<E_OUT> helper, Spliterator<P_IN> spliterator) { return opEvaluateParallel(helper, spliterator, i -> (E_OUT[]) new Object[i]).spliterator();
--- a/src/share/classes/java/util/stream/AbstractShortCircuitTask.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/AbstractShortCircuitTask.java Wed Aug 07 19:56:20 2013 -0700 @@ -39,6 +39,7 @@ * @param <K> type of child and sibling tasks * @since 1.8 */ +@SuppressWarnings("serial") abstract class AbstractShortCircuitTask<P_IN, P_OUT, R, K extends AbstractShortCircuitTask<P_IN, P_OUT, R, K>> extends AbstractTask<P_IN, P_OUT, R, K> { @@ -219,7 +220,8 @@ */ protected void cancelLaterNodes() { // Go up the tree, cancel right siblings of this node and all parents - for (K parent = getParent(), node = (K) this; parent != null; + for (@SuppressWarnings("unchecked") K parent = getParent(), node = (K) this; + parent != null; node = parent, parent = parent.getParent()) { // If node is a left child of parent, then has a right sibling if (parent.leftChild == node) {
--- a/src/share/classes/java/util/stream/AbstractTask.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/AbstractTask.java Wed Aug 07 19:56:20 2013 -0700 @@ -73,6 +73,9 @@ * } * }</pre> * + * <p>Serialization is not supported as there is no intention to serialize + * tasks managed by stream ops. + * * @param <P_IN> Type of elements input to the pipeline * @param <P_OUT> Type of elements output from the pipeline * @param <R> Type of intermediate result, which may be different from operation @@ -80,6 +83,7 @@ * @param <K> Type of parent, child and sibling tasks * @since 1.8 */ +@SuppressWarnings("serial") abstract class AbstractTask<P_IN, P_OUT, R, K extends AbstractTask<P_IN, P_OUT, R, K>> extends CountedCompleter<R> {
--- a/src/share/classes/java/util/stream/Collector.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/Collector.java Wed Aug 07 19:56:20 2013 -0700 @@ -25,40 +25,45 @@ package java.util.stream; import java.util.Collections; +import java.util.EnumSet; import java.util.Set; -import java.util.function.BiFunction; +import java.util.function.BiConsumer; import java.util.function.BinaryOperator; +import java.util.function.Function; import java.util.function.Supplier; /** * A <a href="package-summary.html#Reduction">reduction operation</a> that - * supports folding input elements into a cumulative result. The result may be - * a value or may be a mutable result container. Examples of operations - * accumulating results into a mutable result container include: accumulating - * input elements into a {@code Collection}; concatenating strings into a - * {@code StringBuilder}; computing summary information about elements such as - * sum, min, max, or average; computing "pivot table" summaries such as "maximum - * valued transaction by seller", etc. Reduction operations can be performed - * either sequentially or in parallel. + * folds input elements into a mutable result container, optionally transforming + * the accumulated result into a final representation after all input elements + * have been processed. + * + * <p>Examples of mutable reduction operations include: + * accumulating elements into a {@code Collection}; concatenating + * strings using a {@code StringBuilder}; computing summary information about + * elements such as sum, min, max, or average; computing "pivot table" summaries + * such as "maximum valued transaction by seller", etc. Reduction operations + * can be performed either sequentially or in parallel. * * <p>The following are examples of using the predefined {@code Collector} * implementations in {@link Collectors} with the {@code Stream} API to perform * mutable reduction tasks: * <pre>{@code - * // Accumulate elements into a List - * List<String> list = stream.collect(Collectors.toList()); + * // Accumulate names into a List + * List<String> list = people.stream().map(Person::getName).collect(Collectors.toList()); * - * // Accumulate elements into a TreeSet - * Set<String> list = stream.collect(Collectors.toCollection(TreeSet::new)); + * // Accumulate names into a TreeSet + * Set<String> list = people.stream().map(Person::getName).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(); + * String joined = things.stream() + * .map(Object::toString) + * .collect(Collectors.joining(", ")); * * // Find highest-paid employee * Employee highestPaid = employees.stream() - * .collect(Collectors.maxBy(Comparators.comparing(Employee::getSalary))); + * .collect(Collectors.maxBy(Comparators.comparing(Employee::getSalary))) + * .get(); * * // Group employees by department * Map<Department, List<Employee>> byDept @@ -66,7 +71,7 @@ * .collect(Collectors.groupingBy(Employee::getDepartment)); * * // Find highest-paid employee by department - * Map<Department, Employee> highestPaidByDept + * Map<Department, Optional<Employee>> highestPaidByDept * = employees.stream() * .collect(Collectors.groupingBy(Employee::getDepartment, * Collectors.maxBy(Comparators.comparing(Employee::getSalary)))); @@ -74,43 +79,42 @@ * // Partition students into passing and failing * Map<Boolean, List<Student>> passingFailing = * students.stream() - * .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD); + * .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD)); * * }</pre> * - * <p>A {@code Collector} is specified by three functions that work together to - * manage a result or result container. They are: creation of an initial - * result, incorporating a new data element into a result, and combining two - * results into one. The last function -- combining two results into one -- is - * used during parallel operations, where subsets of the input are accumulated - * in parallel, and then the subresults merged into a combined result. The - * result may be a mutable container or a value. If the result is mutable, the - * accumulation and combination functions may either mutate their left argument - * and return that (such as adding elements to a collection), or return a new - * result, in which case it should not perform any mutation. + * <p>A {@code Collector} is specified by four functions that work together to + * accumulate entries into a mutable result container, and optionally perform + * a final transform on the result. They are: creation of a new result container, + * incorporating a new data element into a result container, combining two + * result containers into one, and performing a final transform on the container. + * The combiner function is used during parallel operations, where + * subsets of the input are accumulated into separate result + * containers, and then the subresults merged into a combined result. The + * combiner function may merge one set of subresults into the other and return + * that, or it may return a new object to describe the combined results. * - * <p>Collectors also have a set of characteristics, including - * {@link Characteristics#CONCURRENT} and - * {@link Characteristics#STRICTLY_MUTATIVE}. These characteristics provide + * <p>Collectors also have a set of characteristics, such as + * {@link Characteristics#CONCURRENT}. These characteristics provide * hints that can be used by a reduction implementation to provide better * performance. * * <p>Libraries that implement reduction based on {@code Collector}, such as * {@link Stream#collect(Collector)}, must adhere to the following constraints: * <ul> - * <li>The first argument passed to the accumulator function, and both - * arguments passed to the combiner function, must be the result of a - * previous invocation of {@link #resultSupplier()}, {@link #accumulator()}, - * or {@link #combiner()}.</li> + * <li>The first argument passed to the accumulator function, both + * arguments passed to the combiner function, and the argument passed to the + * finisher function must be the result of a previous invocation of the + * result supplier, accumulator, or combiner functions.</li> * <li>The implementation should not do anything with the result of any of * the result supplier, accumulator, or combiner functions other than to - * pass them again to the accumulator or combiner functions, or return them - * to the caller of the reduction operation.</li> - * <li>If a result is passed to the accumulator or combiner function, and - * the same object is not returned from that function, it is never used - * again.</li> - * <li>Once a result is passed to the combiner function, it is never passed - * to the accumulator function again.</li> + * pass them again to the accumulator, combiner, or finisher functions, + * or return them to the caller of the reduction operation.</li> + * <li>If a result is passed to the combiner or finisher + * function, and the same object is not returned from that function, it is + * never used again.</li> + * <li>Once a result is passed to the combiner or finisher function, it + * is never passed to the accumulator function again.</li> * <li>For non-concurrent collectors, any result returned from the result * supplier, accumulator, or combiner functions must be serially * thread-confined. This enables collection to occur in parallel without @@ -132,11 +136,10 @@ * Performing a reduction operation with a {@code Collector} should produce a * result equivalent to: * <pre>{@code - * BiFunction<R,T,R> accumulator = collector.accumulator(); - * R result = collector.resultSupplier().get(); + * R container = collector.supplier().get(); * for (T t : data) - * result = accumulator.apply(result, t); - * return result; + * collector.accumulator().accept(container, t); + * return collector.finisher().apply(container); * }</pre> * * <p>However, the library is free to partition the input, perform the reduction @@ -149,7 +152,7 @@ * is accumulating elements into a {@code TreeSet}. In this case, the {@code * resultSupplier()} function is {@code () -> new Treeset<T>()}, the * {@code accumulator} function is - * {@code (set, element) -> { set.add(element); return set; }}, and the combiner + * {@code (set, element) -> set.add(element) }, and the combiner * function is {@code (left, right) -> { left.addAll(right); return left; }}. * (This behavior is implemented by * {@code Collectors.toCollection(TreeSet::new)}). @@ -159,51 +162,49 @@ * @see Stream#collect(Collector) * @see Collectors * - * @param <T> the type of input element to the collect operation - * @param <R> the result type of the collect operation + * @param <T> the type of input elements to the reduction operation + * @param <A> the mutable accumulation type of the reduction operation (often + * hidden as an implementation detail) + * @param <R> the result type of the reduction operation * @since 1.8 */ -public interface Collector<T, R> { +public interface Collector<T, A, R> { /** - * A function that creates and returns a new result that represents - * "no values". If the accumulator or combiner functions may mutate their - * arguments, this must be a new, empty result container. + * A function that creates and returns a new mutable result container. * - * @return a function which, when invoked, returns a result representing - * "no values" + * @return a function which returns a new, mutable result container */ - Supplier<R> resultSupplier(); + Supplier<A> supplier(); /** - * A function that folds a new value into a cumulative result. The result - * may be a mutable result container or a value. The accumulator function - * may modify a mutable container and return it, or create a new result and - * return that, but if it returns a new result object, it must not modify - * any of its arguments. + * A function that folds a new value into a mutable result container. * - * <p>If the collector has the {@link Characteristics#STRICTLY_MUTATIVE} - * characteristic, then the accumulator function <em>must</em> always return - * its first argument, after possibly mutating its state. - * - * @return a function which folds a new value into a cumulative result + * @return a function which folds a new value into a mutable result container */ - BiFunction<R, T, R> accumulator(); + BiConsumer<A, T> accumulator(); /** * A function that accepts two partial results and merges them. The * combiner function may fold state from one argument into the other and - * return that, or may return a new result object, but if it returns - * a new result object, it must not modify the state of either of its - * arguments. - * - * <p>If the collector has the {@link Characteristics#STRICTLY_MUTATIVE} - * characteristic, then the combiner function <em>must</em> always return - * its first argument, after possibly mutating its state. + * return that, or may return a new result object. * * @return a function which combines two partial results into a cumulative * result */ - BinaryOperator<R> combiner(); + BinaryOperator<A> combiner(); + + /** + * Perform the final transformation from the intermediate accumulation type + * {@code A} to the final result representation {@code R}. + * + * <p>If the characteristic {@code IDENTITY_TRANSFORM} is + * set, this function may be presumed to be an identity transform with an + * unchecked cast from {@code A} to {@code R}. + * + * @return a function which transforms the intermediate result to the final + * result + */ + Function<A, R> finisher(); /** * Returns a {@code Set} of {@code Collector.Characteristics} indicating @@ -214,6 +215,62 @@ Set<Characteristics> characteristics(); /** + * Returns a new {@code Collector} described by the given {@code supplier}, + * {@code accumulator}, and {@code combiner} functions. The resulting + * {@code Collector} has the {@code Collector.Characteristics.IDENTITY_FINISH} + * characteristic. + * + * @param supplier The supplier function for the new collector + * @param accumulator The accumulator function for the new collector + * @param combiner The combiner function for the new collector + * @param characteristics The collector characteristics for the new + * collector + * @param <T> The type of input elements for the new collector + * @param <R> The type of intermediate accumulation result, and final result, + * for the new collector + * @return the new {@code Collector} + */ + public static<T, R> Collector<T, R, R> of(Supplier<R> supplier, + BiConsumer<R, T> accumulator, + BinaryOperator<R> combiner, + Characteristics... characteristics) { + Set<Characteristics> cs = (characteristics.length == 0) + ? Collectors.CH_ID + : Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH, + characteristics)); + return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, cs); + } + + /** + * Returns a new {@code Collector} described by the given {@code supplier}, + * {@code accumulator}, {@code combiner}, and {@code finisher} functions. + * + * @param supplier The supplier function for the new collector + * @param accumulator The accumulator function for the new collector + * @param combiner The combiner function for the new collector + * @param finisher The finisher function for the new collector + * @param characteristics The collector characteristics for the new + * collector + * @param <T> The type of input elements for the new collector + * @param <A> The intermediate accumulation type of the new collector + * @param <R> The final result type of the new collector + * @return the new {@code Collector} + */ + public static<T, A, R> Collector<T, A, R> of(Supplier<A> supplier, + BiConsumer<A, T> accumulator, + BinaryOperator<A> combiner, + Function<A, R> finisher, + Characteristics... characteristics) { + Set<Characteristics> cs = Collectors.CH_NOID; + if (characteristics.length > 0) { + cs = EnumSet.noneOf(Characteristics.class); + Collections.addAll(cs, characteristics); + cs = Collections.unmodifiableSet(cs); + } + return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, finisher, cs); + } + + /** * Characteristics indicating properties of a {@code Collector}, which can * be used to optimize reduction implementations. */ @@ -222,8 +279,7 @@ * Indicates that this collector is <em>concurrent</em>, meaning that * the result container can support the accumulator function being * called concurrently with the same result container from multiple - * threads. Concurrent collectors must also always have the - * {@code STRICTLY_MUTATIVE} characteristic. + * threads. * * <p>If a {@code CONCURRENT} collector is not also {@code UNORDERED}, * then it should only be evaluated concurrently if applied to an @@ -238,12 +294,10 @@ UNORDERED, /** - * Indicates that this collector operates by strict mutation of its - * result container. This means that the {@link #accumulator()} and - * {@link #combiner()} functions will always modify the state of and - * return their first argument, rather than returning a different result - * container. + * Indicates that the finisher function is the identity function and + * can be elided. If set, it must be the case that an unchecked cast + * from A to R will succeed. */ - STRICTLY_MUTATIVE + IDENTITY_FINISH } }
--- a/src/share/classes/java/util/stream/Collectors.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/Collectors.java Wed Aug 07 19:56:20 2013 -0700 @@ -27,6 +27,7 @@ import java.util.AbstractMap; import java.util.AbstractSet; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -39,14 +40,16 @@ import java.util.List; import java.util.LongSummaryStatistics; import java.util.Map; -import java.util.NoSuchElementException; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.StringJoiner; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.BinaryOperator; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -64,20 +67,21 @@ * mutable reduction tasks: * * <pre>{@code - * // Accumulate elements into a List - * List<Person> list = people.collect(Collectors.toList()); + * // Accumulate names into a List + * List<String> list = people.stream().map(Person::getName).collect(Collectors.toList()); * - * // Accumulate elements into a TreeSet - * List<Person> list = people.collect(Collectors.toCollection(TreeSet::new)); + * // Accumulate names into a TreeSet + * Set<String> list = people.stream().map(Person::getName).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(); + * String joined = things.stream() + * .map(Object::toString) + * .collect(Collectors.joining(", ")); * * // Find highest-paid employee * Employee highestPaid = employees.stream() - * .collect(Collectors.maxBy(Comparator.comparing(Employee::getSalary))); + * .collect(Collectors.maxBy(Comparator.comparing(Employee::getSalary))) + * .get(); * * // Group employees by department * Map<Department, List<Employee>> byDept @@ -85,7 +89,7 @@ * .collect(Collectors.groupingBy(Employee::getDepartment)); * * // Find highest-paid employee by department - * Map<Department, Employee> highestPaidByDept + * Map<Department, Optional<Employee>> highestPaidByDept * = employees.stream() * .collect(Collectors.groupingBy(Employee::getDepartment, * Collectors.maxBy(Comparator.comparing(Employee::getSalary)))); @@ -93,7 +97,7 @@ * // Partition students into passing and failing * Map<Boolean, List<Student>> passingFailing = * students.stream() - * .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD); + * .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD)); * * }</pre> * @@ -103,15 +107,19 @@ */ public final class Collectors { - private static final Set<Collector.Characteristics> CH_CONCURRENT + static final Set<Collector.Characteristics> CH_CONCURRENT_ID = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT, - Collector.Characteristics.STRICTLY_MUTATIVE, + Collector.Characteristics.UNORDERED, + Collector.Characteristics.IDENTITY_FINISH)); + static final Set<Collector.Characteristics> CH_CONCURRENT_NOID + = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT, Collector.Characteristics.UNORDERED)); - private static final Set<Collector.Characteristics> CH_STRICT - = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.STRICTLY_MUTATIVE)); - private static final Set<Collector.Characteristics> CH_STRICT_UNORDERED - = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.STRICTLY_MUTATIVE, - Collector.Characteristics.UNORDERED)); + static final Set<Collector.Characteristics> CH_ID + = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH)); + static final Set<Collector.Characteristics> CH_UNORDERED_ID + = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED, + Collector.Characteristics.IDENTITY_FINISH)); + static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet(); private Collectors() { } @@ -124,88 +132,64 @@ * * @param <T> the type of input arguments to the merge function * @return a merge function which always throw {@code IllegalStateException} - * - * @see #firstWinsMerger() - * @see #lastWinsMerger() */ - public static <T> BinaryOperator<T> throwingMerger() { + private static <T> BinaryOperator<T> 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 <T> 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 <T> BinaryOperator<T> 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 <T> 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 <T> BinaryOperator<T> lastWinsMerger() { - return (u,v) -> v; - } - - /** * Simple implementation class for {@code Collector}. * * @param <T> the type of elements to be collected * @param <R> the type of the result */ - private static final class CollectorImpl<T, R> implements Collector<T,R> { - private final Supplier<R> resultSupplier; - private final BiFunction<R, T, R> accumulator; - private final BinaryOperator<R> combiner; + static class CollectorImpl<T, A, R> implements Collector<T, A, R> { + private final Supplier<A> supplier; + private final BiConsumer<A, T> accumulator; + private final BinaryOperator<A> combiner; + private final Function<A, R> finisher; private final Set<Characteristics> characteristics; - CollectorImpl(Supplier<R> resultSupplier, - BiFunction<R, T, R> accumulator, - BinaryOperator<R> combiner, + CollectorImpl(Supplier<A> supplier, + BiConsumer<A, T> accumulator, + BinaryOperator<A> combiner, + Function<A,R> finisher, Set<Characteristics> characteristics) { - this.resultSupplier = resultSupplier; + this.supplier = supplier; this.accumulator = accumulator; this.combiner = combiner; + this.finisher = finisher; this.characteristics = characteristics; } - CollectorImpl(Supplier<R> resultSupplier, - BiFunction<R, T, R> accumulator, - BinaryOperator<R> combiner) { - this(resultSupplier, accumulator, combiner, Collections.emptySet()); + CollectorImpl(Supplier<A> supplier, + BiConsumer<A, T> accumulator, + BinaryOperator<A> combiner, + Set<Characteristics> characteristics) { + this(supplier, accumulator, combiner, i -> (R) i, characteristics); } @Override - public BiFunction<R, T, R> accumulator() { + public BiConsumer<A, T> accumulator() { return accumulator; } @Override - public Supplier<R> resultSupplier() { - return resultSupplier; + public Supplier<A> supplier() { + return supplier; } @Override - public BinaryOperator<R> combiner() { + public BinaryOperator<A> combiner() { return combiner; } @Override + public Function<A, R> finisher() { + return finisher; + } + + @Override public Set<Characteristics> characteristics() { return characteristics; } @@ -224,11 +208,10 @@ * {@code Collection}, in encounter order */ public static <T, C extends Collection<T>> - Collector<T, C> toCollection(Supplier<C> collectionFactory) { - return new CollectorImpl<>(collectionFactory, - (r, t) -> { r.add(t); return r; }, + Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) { + return new CollectorImpl<>(collectionFactory, Collection::add, (r1, r2) -> { r1.addAll(r2); return r1; }, - CH_STRICT); + CH_ID); } /** @@ -241,36 +224,10 @@ * {@code List}, in encounter order */ public static <T> - Collector<T, List<T>> toList() { - BiFunction<List<T>, T, List<T>> accumulator = (list, t) -> { - switch (list.size()) { - case 0: - return Collections.singletonList(t); - case 1: - List<T> newList = new ArrayList<>(); - newList.add(list.get(0)); - newList.add(t); - return newList; - default: - list.add(t); - return list; - } - }; - BinaryOperator<List<T>> combiner = (left, right) -> { - switch (left.size()) { - case 0: - return right; - case 1: - List<T> 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); + Collector<T, ?, List<T>> toList() { + return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add, + (left, right) -> { left.addAll(right); return left; }, + CH_ID); } /** @@ -286,44 +243,58 @@ * {@code Set} */ public static <T> - Collector<T, Set<T>> toSet() { - return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, - (r, t) -> { r.add(t); return r; }, - (r1, r2) -> { r1.addAll(r2); return r1; }, - CH_STRICT_UNORDERED); + Collector<T, ?, Set<T>> toSet() { + return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add, + (left, right) -> { left.addAll(right); return left; }, + CH_UNORDERED_ID); } /** * Returns a {@code Collector} that concatenates the input elements into a - * new {@link StringBuilder}. + * {@code String}, in encounter order. * - * @return a {@code Collector} which collects String elements into a - * {@code StringBuilder}, in encounter order + * @return a {@code Collector} that concatenates the input elements into a + * {@code String}, in encounter order */ - public static Collector<String, StringBuilder> toStringBuilder() { - return new CollectorImpl<>(StringBuilder::new, - (r, t) -> { r.append(t); return r; }, - (r1, r2) -> { r1.append(r2); return r1; }, - CH_STRICT); + public static Collector<CharSequence, ?, String> joining() { + return new CollectorImpl<CharSequence, StringBuilder, String>( + StringBuilder::new, StringBuilder::append, + (r1, r2) -> { r1.append(r2); return r1; }, + StringBuilder::toString, CH_NOID); } /** - * Returns a {@code Collector} that concatenates the input elements into a - * new {@link StringJoiner}, using the specified delimiter. + * Returns a {@code Collector} that concatenates the input elements, + * separated by the specified delimiter, in encounter order. * * @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 + * @return A {@code Collector} which concatenates CharSequence elements, + * separated by the specified delimiter, in encounter order */ - public static Collector<CharSequence, StringJoiner> toStringJoiner(CharSequence delimiter) { - BinaryOperator<StringJoiner> 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); + public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) { + return joining(delimiter, "", ""); + } + + /** + * Returns a {@code Collector} that concatenates the input elements, + * separated by the specified delimiter, with the specified prefix and + * suffix, in encounter order. + * + * @param delimiter the delimiter to be used between each element + * @param prefix the sequence of characters to be used at the beginning + * of the joined result + * @param suffix the sequence of characters to be used at the end + * of the joined result + * @return A {@code Collector} which concatenates CharSequence elements, + * separated by the specified delimiter, in encounter order + */ + public static Collector<CharSequence, ?, String> joining(CharSequence delimiter, + CharSequence prefix, + CharSequence suffix) { + return new CollectorImpl<>( + () -> new StringJoiner(delimiter, prefix, suffix), + StringJoiner::add, StringJoiner::merge, + StringJoiner::toString, CH_NOID); } /** @@ -348,12 +319,13 @@ } /** - * Adapts a {@code Collector<U,R>} to a {@code Collector<T,R>} by applying - * a mapping function to each input element before accumulation. + * Adapts a {@code Collector} accepting elements of type {@code U} to one + * accepting elements of type {@code T} by applying a mapping function to + * each input element before accumulation. * * @apiNote * The {@code mapping()} collectors are most useful when used in a - * multi-level reduction, downstream of {@code groupingBy} or + * multi-level reduction, such as downstream of a {@code groupingBy} or * {@code partitioningBy}. For example, given a stream of * {@code Person}, to accumulate the set of last names in each city: * <pre>{@code @@ -364,23 +336,27 @@ * * @param <T> the type of the input elements * @param <U> type of elements accepted by downstream collector + * @param <A> intermediate accumulation type of the downstream collector * @param <R> result type of collector * @param mapper a function to be applied to the input elements * @param downstream a collector which will accept mapped values * @return a collector which applies the mapping function to the input * elements and provides the mapped results to the downstream collector */ - public static <T, U, R> Collector<T, R> - mapping(Function<? super T, ? extends U> mapper, Collector<? super U, R> downstream) { - BiFunction<R, ? super U, R> downstreamAccumulator = downstream.accumulator(); - return new CollectorImpl<>(downstream.resultSupplier(), - (r, t) -> downstreamAccumulator.apply(r, mapper.apply(t)), - downstream.combiner(), downstream.characteristics()); + public static <T, U, A, R> + Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper, + Collector<? super U, A, R> downstream) { + BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator(); + return new CollectorImpl<>(downstream.supplier(), + (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)), + downstream.combiner(), downstream.finisher(), + downstream.characteristics()); } /** - * Returns a {@code Collector<T, Long>} that counts the number of input - * elements. + * Returns a {@code Collector} accepting elements of type {@code T} that + * counts the number of input elements. If no elements are present, the + * result is 0. * * @implSpec * This produces a result equivalent to: @@ -391,14 +367,14 @@ * @param <T> the type of the input elements * @return a {@code Collector} that counts the input elements */ - public static <T> Collector<T, Long> + public static <T> Collector<T, ?, Long> counting() { return reducing(0L, e -> 1L, Long::sum); } /** - * Returns a {@code Collector<T, T>} that produces the minimal element - * according to a given {@code Comparator}. + * Returns a {@code Collector} that produces the minimal element according + * to a given {@code Comparator}, described as an {@code Optional<T>}. * * @implSpec * This produces a result equivalent to: @@ -410,14 +386,14 @@ * @param comparator a {@code Comparator} for comparing elements * @return a {@code Collector} that produces the minimal value */ - public static <T> Collector<T, T> + public static <T> Collector<T, ?, Optional<T>> minBy(Comparator<? super T> comparator) { return reducing(BinaryOperator.minBy(comparator)); } /** - * Returns a {@code Collector<T, T>} that produces the maximal element - * according to a given {@code Comparator}. + * Returns a {@code Collector} that produces the maximal element according + * to a given {@code Comparator}, described as an {@code Optional<T>}. * * @implSpec * This produces a result equivalent to: @@ -429,39 +405,143 @@ * @param comparator a {@code Comparator} for comparing elements * @return a {@code Collector} that produces the maximal value */ - public static <T> Collector<T, T> + public static <T> Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator) { return reducing(BinaryOperator.maxBy(comparator)); } /** - * Returns a {@code Collector<T, Long>} that produces the sum of a - * long-valued function applied to the input element. - * - * @implSpec - * This produces a result equivalent to: - * <pre>{@code - * reducing(0L, mapper, Long::sum) - * }</pre> + * Returns a {@code Collector} that produces the sum of a integer-valued + * function applied to the input elements. If no elements are present, + * the result is 0. * * @param <T> the type of the input elements * @param mapper a function extracting the property to be summed * @return a {@code Collector} that produces the sum of a derived property */ - public static <T> Collector<T, Long> - sumBy(Function<? super T, Long> mapper) { - return reducing(0L, mapper, Long::sum); + public static <T> Collector<T, ?, Integer> + summingInt(ToIntFunction<? super T> mapper) { + return new CollectorImpl<T, int[], Integer>( + () -> new int[1], + (a, t) -> { a[0] += mapper.applyAsInt(t); }, + (a, b) -> { a[0] += b[0]; return a; }, + a -> a[0], CH_NOID); } /** - * Returns a {@code Collector<T,T>} which performs a reduction of its - * input elements under a specified {@code BinaryOperator}. + * Returns a {@code Collector} that produces the sum of a long-valued + * function applied to the input elements. If no elements are present, + * the result is 0. + * + * @param <T> the type of the input elements + * @param mapper a function extracting the property to be summed + * @return a {@code Collector} that produces the sum of a derived property + */ + public static <T> Collector<T, ?, Long> + summingLong(ToLongFunction<? super T> mapper) { + return new CollectorImpl<T, long[], Long>( + () -> new long[1], + (a, t) -> { a[0] += mapper.applyAsLong(t); }, + (a, b) -> { a[0] += b[0]; return a; }, + a -> a[0], CH_NOID); + } + + /** + * Returns a {@code Collector} that produces the sum of a double-valued + * function applied to the input elements. If no elements are present, + * the result is 0. + * + * <p>The sum returned can vary depending upon the order in which + * values are recorded, due to accumulated rounding error in + * addition of values of differing magnitudes. Values sorted by increasing + * absolute magnitude tend to yield more accurate results. If any recorded + * value is a {@code NaN} or the sum is at any point a {@code NaN} then the + * sum will be {@code NaN}. + * + * @param <T> the type of the input elements + * @param mapper a function extracting the property to be summed + * @return a {@code Collector} that produces the sum of a derived property + */ + public static <T> Collector<T, ?, Double> + summingDouble(ToDoubleFunction<? super T> mapper) { + return new CollectorImpl<T, double[], Double>( + () -> new double[1], + (a, t) -> { a[0] += mapper.applyAsDouble(t); }, + (a, b) -> { a[0] += b[0]; return a; }, + a -> a[0], CH_NOID); + } + + /** + * Returns a {@code Collector} that produces the arithmetic mean of an integer-valued + * function applied to the input elements. If no elements are present, + * the result is 0. + * + * @param <T> the type of the input elements + * @param mapper a function extracting the property to be summed + * @return a {@code Collector} that produces the sum of a derived property + */ + public static <T> Collector<T, ?, Double> + averagingInt(ToIntFunction<? super T> mapper) { + return new CollectorImpl<T, long[], Double>( + () -> new long[2], + (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; }, + (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, + a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID); + } + + /** + * Returns a {@code Collector} that produces the arithmetic mean of a long-valued + * function applied to the input elements. If no elements are present, + * the result is 0. + * + * @param <T> the type of the input elements + * @param mapper a function extracting the property to be summed + * @return a {@code Collector} that produces the sum of a derived property + */ + public static <T> Collector<T, ?, Double> + averagingLong(ToLongFunction<? super T> mapper) { + return new CollectorImpl<T, long[], Double>( + () -> new long[2], + (a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; }, + (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, + a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID); + } + + /** + * Returns a {@code Collector} that produces the arithmetic mean of a double-valued + * function applied to the input elements. If no elements are present, + * the result is 0. + * + * <p>The average returned can vary depending upon the order in which + * values are recorded, due to accumulated rounding error in + * addition of values of differing magnitudes. Values sorted by increasing + * absolute magnitude tend to yield more accurate results. If any recorded + * value is a {@code NaN} or the sum is at any point a {@code NaN} then the + * average will be {@code NaN}. + * + * @param <T> the type of the input elements + * @param mapper a function extracting the property to be summed + * @return a {@code Collector} that produces the sum of a derived property + */ + public static <T> Collector<T, ?, Double> + averagingDouble(ToDoubleFunction<? super T> mapper) { + return new CollectorImpl<T, double[], Double>( + () -> new double[2], + (a, t) -> { a[0] += mapper.applyAsDouble(t); a[1]++; }, + (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, + a -> (a[1] == 0) ? 0.0d : a[0] / a[1], CH_NOID); + } + + /** + * Returns a {@code Collector} which performs a reduction of its + * input elements under a specified {@code BinaryOperator} using the + * provided identity. * * @apiNote * The {@code reducing()} collectors are most useful when used in a * multi-level reduction, downstream of {@code groupingBy} or * {@code partitioningBy}. To perform a simple reduction on a stream, - * use {@link Stream#reduce(BinaryOperator)} instead. + * use {@link Stream#reduce(Object, BinaryOperator)}} instead. * * @param <T> element type for the input and output of the reduction * @param identity the identity value for the reduction (also, the value @@ -472,14 +552,25 @@ * @see #reducing(BinaryOperator) * @see #reducing(Object, Function, BinaryOperator) */ - public static <T> Collector<T, T> + public static <T> Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op) { - return new CollectorImpl<>(() -> identity, (r, t) -> (r == null ? t : op.apply(r, t)), op); + return new CollectorImpl<>( + boxSupplier(identity), + (a, t) -> { a[0] = op.apply(a[0], t); }, + (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; }, + a -> a[0], + CH_NOID); + } + + @SuppressWarnings("unchecked") + private static <T> Supplier<T[]> boxSupplier(T identity) { + return () -> (T[]) new Object[] { identity }; } /** - * Returns a {@code Collector<T,T>} which performs a reduction of its - * input elements under a specified {@code BinaryOperator}. + * Returns a {@code Collector} which performs a reduction of its + * input elements under a specified {@code BinaryOperator}. The result + * is described as an {@code Optional<T>}. * * @apiNote * The {@code reducing()} collectors are most useful when used in a @@ -491,15 +582,8 @@ * person in each city: * <pre>{@code * Comparator<Person> byHeight = Comparator.comparing(Person::getHeight); - * BinaryOperator<Person> tallerOf = BinaryOperator.greaterOf(byHeight); * Map<City, Person> tallestByCity - * = people.stream().collect(groupingBy(Person::getCity, reducing(tallerOf))); - * }</pre> - * - * @implSpec - * The default implementation is equivalent to: - * <pre>{@code - * reducing(null, op); + * = people.stream().collect(groupingBy(Person::getCity, reducing(BinaryOperator.maxBy(byHeight)))); * }</pre> * * @param <T> element type for the input and output of the reduction @@ -509,13 +593,32 @@ * @see #reducing(Object, BinaryOperator) * @see #reducing(Object, Function, BinaryOperator) */ - public static <T> Collector<T, T> + public static <T> Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op) { - return reducing(null, op); + class OptionalBox implements Consumer<T> { + T value = null; + boolean present = false; + + @Override + public void accept(T t) { + if (present) { + value = op.apply(value, t); + } + else { + value = t; + present = true; + } + } + } + + return new CollectorImpl<T, OptionalBox, Optional<T>>( + OptionalBox::new, OptionalBox::accept, + (a, b) -> { if (b.present) a.accept(b.value); return a; }, + a -> Optional.ofNullable(a.value), CH_NOID); } /** - * Returns a {@code Collector<T,U>} which performs a reduction of its + * Returns a {@code Collector} which performs a reduction of its * input elements under a specified mapping function and * {@code BinaryOperator}. This is a generalization of * {@link #reducing(Object, BinaryOperator)} which allows a transformation @@ -524,17 +627,17 @@ * @apiNote * The {@code reducing()} collectors are most useful when used in a * multi-level reduction, downstream of {@code groupingBy} or - * {@code partitioningBy}. To perform a simple reduction on a stream, - * use {@link Stream#reduce(BinaryOperator)} instead. + * {@code partitioningBy}. To perform a simple map-reduce on a stream, + * use {@link Stream#map(Function)} and {@link Stream#reduce(Object, BinaryOperator)} + * instead. * * <p>For example, given a stream of {@code Person}, to calculate the longest * last name of residents in each city: * <pre>{@code * Comparator<String> byLength = Comparator.comparing(String::length); - * BinaryOperator<String> longerOf = BinaryOperator.greaterOf(byLength); * Map<City, String> longestLastNameByCity * = people.stream().collect(groupingBy(Person::getCity, - * reducing(Person::getLastName, longerOf))); + * reducing(Person::getLastName, BinaryOperator.maxBy(byLength)))); * }</pre> * * @param <T> the type of the input elements @@ -549,18 +652,20 @@ * @see #reducing(BinaryOperator) */ public static <T, U> - Collector<T, U> reducing(U identity, - Function<? super T, ? extends U> mapper, - BinaryOperator<U> op) { - return new CollectorImpl<>(() -> identity, - (r, t) -> (r == null ? mapper.apply(t) : op.apply(r, mapper.apply(t))), - op); + Collector<T, ?, U> reducing(U identity, + Function<? super T, ? extends U> mapper, + BinaryOperator<U> op) { + return new CollectorImpl<>( + boxSupplier(identity), + (a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); }, + (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; }, + a -> a[0], CH_NOID); } /** * Returns a {@code Collector} implementing a "group by" operation on * input elements of type {@code T}, grouping elements according to a - * classification function. + * classification function, and returning the results in a {@code Map}. * * <p>The classification function maps elements to some key type {@code K}. * The collector produces a {@code Map<K, List<T>>} whose keys are the @@ -586,9 +691,9 @@ * @see #groupingBy(Function, Supplier, Collector) * @see #groupingByConcurrent(Function) */ - public static <T, K> - Collector<T, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier) { - return groupingBy(classifier, HashMap::new, toList()); + public static <T, K> Collector<T, ?, Map<K, List<T>>> + groupingBy(Function<? super T, ? extends K> classifier) { + return groupingBy(classifier, toList()); } /** @@ -615,6 +720,7 @@ * * @param <T> the type of the input elements * @param <K> the type of the keys + * @param <A> the intermediate accumulation type of the downstream collector * @param <D> the result type of the downstream reduction * @param classifier a classifier function mapping input elements to keys * @param downstream a {@code Collector} implementing the downstream reduction @@ -624,9 +730,9 @@ * @see #groupingBy(Function, Supplier, Collector) * @see #groupingByConcurrent(Function, Collector) */ - public static <T, K, D> - Collector<T, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, - Collector<? super T, D> downstream) { + public static <T, K, A, D> + Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, + Collector<? super T, A, D> downstream) { return groupingBy(classifier, HashMap::new, downstream); } @@ -653,6 +759,7 @@ * * @param <T> the type of the input elements * @param <K> the type of the keys + * @param <A> the intermediate accumulation type of the downstream collector * @param <D> the result type of the downstream reduction * @param <M> the type of the resulting {@code Map} * @param classifier a classifier function mapping input elements to keys @@ -665,25 +772,39 @@ * @see #groupingBy(Function) * @see #groupingByConcurrent(Function, Supplier, Collector) */ - public static <T, K, D, M extends Map<K, D>> - Collector<T, M> groupingBy(Function<? super T, ? extends K> classifier, - Supplier<M> mapFactory, - Collector<? super T, D> downstream) { - Supplier<D> downstreamSupplier = downstream.resultSupplier(); - BiFunction<D, ? super T, D> downstreamAccumulator = downstream.accumulator(); - BiFunction<M, T, M> accumulator = (m, t) -> { + public static <T, K, D, A, M extends Map<K, D>> + Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier, + Supplier<M> mapFactory, + Collector<? super T, A, D> downstream) { + Supplier<A> downstreamSupplier = downstream.supplier(); + BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator(); + BiConsumer<Map<K, A>, T> accumulator = (m, t) -> { K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); - D oldContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get()); - D newContainer = downstreamAccumulator.apply(oldContainer, t); - if (newContainer != oldContainer) - m.put(key, newContainer); - return m; + A container = m.computeIfAbsent(key, k -> downstreamSupplier.get()); + downstreamAccumulator.accept(container, t); }; - return new CollectorImpl<>(mapFactory, accumulator, mapMerger(downstream.combiner()), CH_STRICT); + BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner()); + @SuppressWarnings("unchecked") + Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory; + + if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { + return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID); + } + else { + @SuppressWarnings("unchecked") + Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher(); + Function<Map<K, A>, M> finisher = intermediate -> { + intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v)); + @SuppressWarnings("unchecked") + M castResult = (M) intermediate; + return castResult; + }; + return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID); + } } /** - * Returns a {@code Collector} implementing a concurrent "group by" + * Returns a concurrent {@code Collector} implementing a "group by" * operation on input elements of type {@code T}, grouping elements * according to a classification function. * @@ -716,12 +837,13 @@ * @see #groupingByConcurrent(Function, Supplier, Collector) */ public static <T, K> - Collector<T, ConcurrentMap<K, List<T>>> groupingByConcurrent(Function<? super T, ? extends K> classifier) { + Collector<T, ?, ConcurrentMap<K, List<T>>> + groupingByConcurrent(Function<? super T, ? extends K> classifier) { return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList()); } /** - * Returns a {@code Collector} implementing a concurrent cascaded "group by" + * Returns a concurrent {@code Collector} implementing a cascaded "group by" * operation on input elements of type {@code T}, grouping elements * according to a classification function, and then performing a reduction * operation on the values associated with a given key using the specified @@ -739,12 +861,13 @@ * where the city names are sorted: * <pre>{@code * ConcurrentMap<City, Set<String>> namesByCity - * = people.stream().collect(groupingByConcurrent(Person::getCity, TreeMap::new, + * = people.stream().collect(groupingByConcurrent(Person::getCity, ConcurrentSkipListMap::new, * mapping(Person::getLastName, toSet()))); * }</pre> * * @param <T> the type of the input elements * @param <K> the type of the keys + * @param <A> the intermediate accumulation type of the downstream collector * @param <D> the result type of the downstream reduction * @param classifier a classifier function mapping input elements to keys * @param downstream a {@code Collector} implementing the downstream reduction @@ -754,9 +877,9 @@ * @see #groupingByConcurrent(Function) * @see #groupingByConcurrent(Function, Supplier, Collector) */ - public static <T, K, D> - Collector<T, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier, - Collector<? super T, D> downstream) { + public static <T, K, A, D> + Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier, + Collector<? super T, A, D> downstream) { return groupingByConcurrent(classifier, ConcurrentHashMap::new, downstream); } @@ -787,6 +910,7 @@ * * @param <T> the type of the input elements * @param <K> the type of the keys + * @param <A> the intermediate accumulation type of the downstream collector * @param <D> the result type of the downstream reduction * @param <M> the type of the resulting {@code ConcurrentMap} * @param classifier a classifier function mapping input elements to keys @@ -799,51 +923,46 @@ * @see #groupingByConcurrent(Function, Collector) * @see #groupingBy(Function, Supplier, Collector) */ - public static <T, K, D, M extends ConcurrentMap<K, D>> - Collector<T, M> groupingByConcurrent(Function<? super T, ? extends K> classifier, - Supplier<M> mapFactory, - Collector<? super T, D> downstream) { - Supplier<D> downstreamSupplier = downstream.resultSupplier(); - BiFunction<D, ? super T, D> downstreamAccumulator = downstream.accumulator(); - BinaryOperator<M> combiner = mapMerger(downstream.combiner()); + public static <T, K, A, D, M extends ConcurrentMap<K, D>> + Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier, + Supplier<M> mapFactory, + Collector<? super T, A, D> downstream) { + Supplier<A> downstreamSupplier = downstream.supplier(); + BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator(); + BinaryOperator<ConcurrentMap<K, A>> merger = Collectors.<K, A, ConcurrentMap<K, A>>mapMerger(downstream.combiner()); + @SuppressWarnings("unchecked") + Supplier<ConcurrentMap<K, A>> mangledFactory = (Supplier<ConcurrentMap<K, A>>) mapFactory; + BiConsumer<ConcurrentMap<K, A>, T> accumulator; if (downstream.characteristics().contains(Collector.Characteristics.CONCURRENT)) { - BiFunction<M, T, M> accumulator = (m, t) -> { + accumulator = (m, t) -> { K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); - downstreamAccumulator.apply(m.computeIfAbsent(key, k -> downstreamSupplier.get()), t); - return m; + A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get()); + downstreamAccumulator.accept(resultContainer, t); }; - return new CollectorImpl<>(mapFactory, accumulator, combiner, CH_CONCURRENT); - } else if (downstream.characteristics().contains(Collector.Characteristics.STRICTLY_MUTATIVE)) { - BiFunction<M, T, M> accumulator = (m, t) -> { + } + else { + accumulator = (m, t) -> { K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); - D resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get()); + A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get()); synchronized (resultContainer) { - downstreamAccumulator.apply(resultContainer, t); + downstreamAccumulator.accept(resultContainer, t); } - return m; }; - return new CollectorImpl<>(mapFactory, accumulator, combiner, CH_CONCURRENT); - } else { - BiFunction<M, T, M> accumulator = (m, t) -> { - K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); - do { - D oldResult = m.computeIfAbsent(key, k -> downstreamSupplier.get()); - if (oldResult == null) { - if (m.putIfAbsent(key, downstreamAccumulator.apply(null, t)) == null) - return m; - } else { - synchronized (oldResult) { - if (m.get(key) != oldResult) - continue; - D newResult = downstreamAccumulator.apply(oldResult, t); - if (oldResult != newResult) - m.put(key, newResult); - return m; - } - } - } while (true); + } + + if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { + return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_CONCURRENT_ID); + } + else { + @SuppressWarnings("unchecked") + Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher(); + Function<ConcurrentMap<K, A>, M> finisher = intermediate -> { + intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v)); + @SuppressWarnings("unchecked") + M castResult = (M) intermediate; + return castResult; }; - return new CollectorImpl<>(mapFactory, accumulator, combiner, CH_CONCURRENT); + return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID); } } @@ -862,7 +981,7 @@ * @see #partitioningBy(Predicate, Collector) */ public static <T> - Collector<T, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) { + Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) { return partitioningBy(predicate, toList()); } @@ -877,6 +996,7 @@ * serializability, or thread-safety of the {@code Map} returned. * * @param <T> the type of the input elements + * @param <A> the intermediate accumulation type of the downstream collector * @param <D> the result type of the downstream reduction * @param predicate a predicate used for classifying input elements * @param downstream a {@code Collector} implementing the downstream @@ -886,52 +1006,43 @@ * * @see #partitioningBy(Predicate) */ - public static <T, D> - Collector<T, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate, - Collector<? super T, D> downstream) { - BiFunction<D, ? super T, D> downstreamAccumulator = downstream.accumulator(); - BiFunction<Map<Boolean, D>, T, Map<Boolean, D>> accumulator = (result, t) -> { + public static <T, D, A> + Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate, + Collector<? super T, A, D> downstream) { + @SuppressWarnings("unchecked") + BiConsumer<D, ? super T> downstreamAccumulator = (BiConsumer<D, ? super T>) downstream.accumulator(); + BiConsumer<Map<Boolean, A>, T> accumulator = (result, t) -> { Partition<D> asPartition = ((Partition<D>) result); - if (predicate.test(t)) { - D newResult = downstreamAccumulator.apply(asPartition.forTrue, t); - if (newResult != asPartition.forTrue) - asPartition.forTrue = newResult; - } else { - D newResult = downstreamAccumulator.apply(asPartition.forFalse, t); - if (newResult != asPartition.forFalse) - asPartition.forFalse = newResult; - } - return result; + downstreamAccumulator.accept(predicate.test(t) ? asPartition.forTrue : asPartition.forFalse, t); }; - return new CollectorImpl<>(() -> new Partition<>(downstream.resultSupplier().get(), - downstream.resultSupplier().get()), - accumulator, partitionMerger(downstream.combiner()), CH_STRICT); + BinaryOperator<A> op = downstream.combiner(); + BinaryOperator<Map<Boolean, A>> merger = (m1, m2) -> { + Partition<A> left = (Partition<A>) m1; + Partition<A> right = (Partition<A>) m2; + return new Partition<>(op.apply(left.forTrue, right.forTrue), + op.apply(left.forFalse, right.forFalse)); + }; + Supplier<Map<Boolean, A>> supplier = () -> new Partition<>(downstream.supplier().get(), + downstream.supplier().get()); + if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { + return new CollectorImpl<>(supplier, accumulator, merger, CH_ID); + } + else { + Function<Map<Boolean, A>, Map<Boolean, D>> finisher = (Map<Boolean, A> par) -> { + Partition<A> asAPartition = (Partition<A>) par; + return new Partition<>(downstream.finisher().apply(asAPartition.forTrue), + downstream.finisher().apply(asAPartition.forFalse)); + }; + return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID); + } } /** - * Merge function for two partitions, given a merge function for the - * elements. - */ - private static <D> BinaryOperator<Map<Boolean, D>> partitionMerger(BinaryOperator<D> op) { - return (m1, m2) -> { - Partition<D> left = (Partition<D>) m1; - Partition<D> right = (Partition<D>) m2; - if (left.forFalse == null) - left.forFalse = right.forFalse; - else if (right.forFalse != null) - left.forFalse = op.apply(left.forFalse, right.forFalse); - if (left.forTrue == null) - left.forTrue = right.forTrue; - else if (right.forTrue != null) - left.forTrue = op.apply(left.forTrue, right.forTrue); - return left; - }; - } - - /** - * Accumulate elements into a {@code Map} whose keys and values are the - * result of applying mapping functions to the input elements. - * If the mapped keys contains duplicates (according to + * Returns a {@code Collector} that accumulate elements into a + * {@code Map} whose keys and values are the result of applying the provided + * mapping functions to the input elements. + * + * <p>If the mapped keys contains duplicates (according to * {@link Object#equals(Object)}), an {@code IllegalStateException} is * thrown when the collection operation is performed. If the mapped keys * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)} @@ -970,24 +1081,26 @@ * @see #toConcurrentMap(Function, Function) */ public static <T, K, U> - Collector<T, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, - Function<? super T, ? extends U> valueMapper) { + Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, + Function<? super T, ? extends U> valueMapper) { return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new); } /** - * Accumulate elements into a {@code Map} whose keys and values are the - * result of applying mapping functions to the input elements. If the mapped + * Returns a {@code Collector} that accumulate elements into a + * {@code Map} whose keys and values are the result of applying the provided + * mapping functions to the input elements. + * + * <p>If the mapped * keys contains duplicates (according to {@link Object#equals(Object)}), * the value mapping function is applied to each equal element, and the * results are merged using the provided merging function. * * @apiNote * There are multiple ways to deal with collisions between multiple elements - * mapping to the same key. There are some predefined merging functions, - * such as {@link #throwingMerger()}, {@link #firstWinsMerger()}, and - * {@link #lastWinsMerger()}, that implement common policies, or you can - * implement custom policies easily. For example, if you have a stream + * mapping to the same key. The other forms of {@code toMap} simply use + * a merge function that throws unconditionally, but you can easily write + * more flexible merge policies. For example, if you have a stream * of {@code Person}, and you want to produce a "phone book" mapping name to * address, but it is possible that two persons have the same name, you can * do as follows to gracefully deals with these collisions, and produce a @@ -1018,15 +1131,18 @@ * @see #toConcurrentMap(Function, Function, BinaryOperator) */ public static <T, K, U> - Collector<T, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, - Function<? super T, ? extends U> valueMapper, - BinaryOperator<U> mergeFunction) { + Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, + Function<? super T, ? extends U> valueMapper, + BinaryOperator<U> mergeFunction) { return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); } /** - * Accumulate elements into a {@code Map} whose keys and values are the - * result of applying mapping functions to the input elements. If the mapped + * Returns a {@code Collector} that accumulate elements into a + * {@code Map} whose keys and values are the result of applying the provided + * mapping functions to the input elements. + * + * <p>If the mapped * keys contains duplicates (according to {@link Object#equals(Object)}), * the value mapping function is applied to each equal element, and the * results are merged using the provided merging function. The {@code Map} @@ -1054,22 +1170,22 @@ * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier) */ public static <T, K, U, M extends Map<K, U>> - Collector<T, M> toMap(Function<? super T, ? extends K> keyMapper, - Function<? super T, ? extends U> valueMapper, - BinaryOperator<U> mergeFunction, - Supplier<M> mapSupplier) { - BiFunction<M, T, M> accumulator - = (map, element) -> { - map.merge(keyMapper.apply(element), valueMapper.apply(element), mergeFunction); - return map; - }; - return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_STRICT); + Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper, + Function<? super T, ? extends U> valueMapper, + BinaryOperator<U> mergeFunction, + Supplier<M> mapSupplier) { + BiConsumer<M, T> accumulator + = (map, element) -> map.merge(keyMapper.apply(element), + valueMapper.apply(element), mergeFunction); + return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID); } /** - * Accumulate elements into a {@code ConcurrentMap} whose keys and values - * are the result of applying mapping functions to the input elements. - * If the mapped keys contains duplicates (according to + * Returns a {@code Collector} that accumulate elements into a + * {@code ConcurrentMap} whose keys and values are the result of applying + * the provided mapping functions to the input elements. + * + * <p>If the mapped keys contains duplicates (according to * {@link Object#equals(Object)}), an {@code IllegalStateException} is * thrown when the collection operation is performed. If the mapped keys * may have duplicates, use @@ -1112,24 +1228,25 @@ * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier) */ public static <T, K, U> - Collector<T, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper, - Function<? super T, ? extends U> valueMapper) { + Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper, + Function<? super T, ? extends U> valueMapper) { return toConcurrentMap(keyMapper, valueMapper, throwingMerger(), ConcurrentHashMap::new); } /** - * Accumulate elements into a {@code ConcurrentMap} whose keys and values - * are the result of applying mapping functions to the input elements. If - * the mapped keys contains duplicates (according to {@link Object#equals(Object)}), + * Returns a {@code Collector} that accumulate elements into a + * {@code ConcurrentMap} whose keys and values are the result of applying + * the provided mapping functions to the input elements. + * + * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}), * the value mapping function is applied to each equal element, and the * results are merged using the provided merging function. * * @apiNote * There are multiple ways to deal with collisions between multiple elements - * mapping to the same key. There are some predefined merging functions, - * such as {@link #throwingMerger()}, {@link #firstWinsMerger()}, and - * {@link #lastWinsMerger()}, that implement common policies, or you can - * implement custom policies easily. For example, if you have a stream + * mapping to the same key. The other forms of {@code toConcurrentMap} simply use + * a merge function that throws unconditionally, but you can easily write + * more flexible merge policies. For example, if you have a stream * of {@code Person}, and you want to produce a "phone book" mapping name to * address, but it is possible that two persons have the same name, you can * do as follows to gracefully deals with these collisions, and produce a @@ -1163,16 +1280,19 @@ * @see #toMap(Function, Function, BinaryOperator) */ public static <T, K, U> - Collector<T, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper, - Function<? super T, ? extends U> valueMapper, - BinaryOperator<U> mergeFunction) { + Collector<T, ?, ConcurrentMap<K,U>> + toConcurrentMap(Function<? super T, ? extends K> keyMapper, + Function<? super T, ? extends U> valueMapper, + BinaryOperator<U> mergeFunction) { return toConcurrentMap(keyMapper, valueMapper, mergeFunction, ConcurrentHashMap::new); } /** - * Accumulate elements into a {@code ConcurrentMap} whose keys and values - * are the result of applying mapping functions to the input elements. If - * the mapped keys contains duplicates (according to {@link Object#equals(Object)}), + * Returns a {@code Collector} that accumulate elements into a + * {@code ConcurrentMap} whose keys and values are the result of applying + * the provided mapping functions to the input elements. + * + * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}), * the value mapping function is applied to each equal element, and the * results are merged using the provided merging function. The * {@code ConcurrentMap} is created by a provided supplier function. @@ -1202,15 +1322,14 @@ * @see #toMap(Function, Function, BinaryOperator, Supplier) */ public static <T, K, U, M extends ConcurrentMap<K, U>> - Collector<T, M> toConcurrentMap(Function<? super T, ? extends K> keyMapper, - Function<? super T, ? extends U> valueMapper, - BinaryOperator<U> mergeFunction, - Supplier<M> mapSupplier) { - BiFunction<M, T, M> accumulator = (map, element) -> { - map.merge(keyMapper.apply(element), valueMapper.apply(element), mergeFunction); - return map; - }; - return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_CONCURRENT); + Collector<T, ?, M> toConcurrentMap(Function<? super T, ? extends K> keyMapper, + Function<? super T, ? extends U> valueMapper, + BinaryOperator<U> mergeFunction, + Supplier<M> mapSupplier) { + BiConsumer<M, T> accumulator + = (map, element) -> map.merge(keyMapper.apply(element), + valueMapper.apply(element), mergeFunction); + return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_CONCURRENT_ID); } /** @@ -1222,14 +1341,15 @@ * @param mapper a mapping function to apply to each element * @return a {@code Collector} implementing the summary-statistics reduction * - * @see #toDoubleSummaryStatistics(ToDoubleFunction) - * @see #toLongSummaryStatistics(ToLongFunction) + * @see #summarizingDouble(ToDoubleFunction) + * @see #summarizingLong(ToLongFunction) */ public static <T> - Collector<T, IntSummaryStatistics> toIntSummaryStatistics(ToIntFunction<? super T> mapper) { - return new CollectorImpl<>(IntSummaryStatistics::new, - (r, t) -> { r.accept(mapper.applyAsInt(t)); return r; }, - (l, r) -> { l.combine(r); return l; }, CH_STRICT); + Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) { + return new CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>( + IntSummaryStatistics::new, + (r, t) -> r.accept(mapper.applyAsInt(t)), + (l, r) -> { l.combine(r); return l; }, CH_ID); } /** @@ -1241,14 +1361,15 @@ * @param mapper the mapping function to apply to each element * @return a {@code Collector} implementing the summary-statistics reduction * - * @see #toDoubleSummaryStatistics(ToDoubleFunction) - * @see #toIntSummaryStatistics(ToIntFunction) + * @see #summarizingDouble(ToDoubleFunction) + * @see #summarizingInt(ToIntFunction) */ public static <T> - Collector<T, LongSummaryStatistics> toLongSummaryStatistics(ToLongFunction<? super T> mapper) { - return new CollectorImpl<>(LongSummaryStatistics::new, - (r, t) -> { r.accept(mapper.applyAsLong(t)); return r; }, - (l, r) -> { l.combine(r); return l; }, CH_STRICT); + Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) { + return new CollectorImpl<T, LongSummaryStatistics, LongSummaryStatistics>( + LongSummaryStatistics::new, + (r, t) -> r.accept(mapper.applyAsLong(t)), + (l, r) -> { l.combine(r); return l; }, CH_ID); } /** @@ -1260,14 +1381,15 @@ * @param mapper a mapping function to apply to each element * @return a {@code Collector} implementing the summary-statistics reduction * - * @see #toLongSummaryStatistics(ToLongFunction) - * @see #toIntSummaryStatistics(ToIntFunction) + * @see #summarizingLong(ToLongFunction) + * @see #summarizingInt(ToIntFunction) */ public static <T> - Collector<T, DoubleSummaryStatistics> toDoubleSummaryStatistics(ToDoubleFunction<? super T> mapper) { - return new CollectorImpl<>(DoubleSummaryStatistics::new, - (r, t) -> { r.accept(mapper.applyAsDouble(t)); return r; }, - (l, r) -> { l.combine(r); return l; }, CH_STRICT); + Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) { + return new CollectorImpl<T, DoubleSummaryStatistics, DoubleSummaryStatistics>( + DoubleSummaryStatistics::new, + (r, t) -> r.accept(mapper.applyAsDouble(t)), + (l, r) -> { l.combine(r); return l; }, CH_ID); } /** @@ -1276,8 +1398,8 @@ private static final class Partition<T> extends AbstractMap<Boolean, T> implements Map<Boolean, T> { - T forTrue; - T forFalse; + final T forTrue; + final T forFalse; Partition(T forTrue, T forFalse) { this.forTrue = forTrue; @@ -1289,24 +1411,9 @@ return new AbstractSet<Map.Entry<Boolean, T>>() { @Override public Iterator<Map.Entry<Boolean, T>> iterator() { - - return new Iterator<Map.Entry<Boolean, T>>() { - int state = 0; - - @Override - public boolean hasNext() { - return state < 2; - } - - @Override - public Map.Entry<Boolean, T> next() { - if (state >= 2) - throw new NoSuchElementException(); - return (state++ == 0) - ? new SimpleImmutableEntry<>(false, forFalse) - : new SimpleImmutableEntry<>(true, forTrue); - } - }; + Map.Entry<Boolean, T> falseEntry = new SimpleImmutableEntry<>(false, forFalse); + Map.Entry<Boolean, T> trueEntry = new SimpleImmutableEntry<>(true, forTrue); + return Arrays.asList(falseEntry, trueEntry).iterator(); } @Override
--- a/src/share/classes/java/util/stream/DelegatingStream.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/DelegatingStream.java Wed Aug 07 19:56:20 2013 -0700 @@ -209,7 +209,7 @@ } @Override - public <R> R collect(Collector<? super T, R> collector) { + public <R, A> R collect(Collector<? super T, A, ? extends R> collector) { return delegate.collect(collector); }
--- a/src/share/classes/java/util/stream/DoublePipeline.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/DoublePipeline.java Wed Aug 07 19:56:20 2013 -0700 @@ -147,6 +147,7 @@ } @Override + @SuppressWarnings("unchecked") final Spliterator.OfDouble lazySpliterator(Supplier<? extends Spliterator<Double>> supplier) { return new StreamSpliterators.DelegatingSpliterator.OfDouble((Supplier<Spliterator.OfDouble>) supplier); } @@ -209,6 +210,7 @@ Sink<Double> opWrapSink(int flags, Sink<U> sink) { return new Sink.ChainedDouble(sink) { @Override + @SuppressWarnings("unchecked") public void accept(double t) { downstream.accept(mapper.apply(t)); }
--- a/src/share/classes/java/util/stream/DoubleStream.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/DoubleStream.java Wed Aug 07 19:56:20 2013 -0700 @@ -527,7 +527,7 @@ long count(); /** - * Returns an {@code OptionalDouble} describing the average of elements of + * Returns an {@code OptionalDouble} describing the arithmetic mean of elements of * this stream, or an empty optional if this stream is empty. The average * returned can vary depending upon the order in which elements are * encountered. This is due to accumulated rounding error in addition of
--- a/src/share/classes/java/util/stream/FindOps.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/FindOps.java Wed Aug 07 19:56:20 2013 -0700 @@ -246,6 +246,7 @@ * @param <P_OUT> Output element type from the stream pipeline * @param <O> Result type from the find operation */ + @SuppressWarnings("serial") private static final class FindTask<P_IN, P_OUT, O> extends AbstractShortCircuitTask<P_IN, P_OUT, O, FindTask<P_IN, P_OUT, O>> { private final FindOp<P_OUT, O> op;
--- a/src/share/classes/java/util/stream/ForEachOps.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/ForEachOps.java Wed Aug 07 19:56:20 2013 -0700 @@ -249,6 +249,7 @@ } /** A {@code ForkJoinTask} for performing a parallel for-each operation */ + @SuppressWarnings("serial") static final class ForEachTask<S, T> extends CountedCompleter<Void> { private Spliterator<S> spliterator; private final Sink<S> sink; @@ -314,6 +315,7 @@ * A {@code ForkJoinTask} for performing a parallel for-each operation * which visits the elements in encounter order */ + @SuppressWarnings("serial") static final class ForEachOrderedTask<S, T> extends CountedCompleter<Void> { private final PipelineHelper<T> helper; private Spliterator<S> spliterator;
--- a/src/share/classes/java/util/stream/IntPipeline.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/IntPipeline.java Wed Aug 07 19:56:20 2013 -0700 @@ -150,6 +150,7 @@ } @Override + @SuppressWarnings("unchecked") final Spliterator.OfInt lazySpliterator(Supplier<? extends Spliterator<Integer>> supplier) { return new StreamSpliterators.DelegatingSpliterator.OfInt((Supplier<Spliterator.OfInt>) supplier); } @@ -190,6 +191,7 @@ Sink<Integer> opWrapSink(int flags, Sink<Long> sink) { return new Sink.ChainedInt(sink) { @Override + @SuppressWarnings("unchecked") public void accept(int t) { downstream.accept((long) t); } @@ -206,6 +208,7 @@ Sink<Integer> opWrapSink(int flags, Sink<Double> sink) { return new Sink.ChainedInt(sink) { @Override + @SuppressWarnings("unchecked") public void accept(int t) { downstream.accept((double) t); } @@ -245,6 +248,7 @@ Sink<Integer> opWrapSink(int flags, Sink<U> sink) { return new Sink.ChainedInt(sink) { @Override + @SuppressWarnings("unchecked") public void accept(int t) { downstream.accept(mapper.apply(t)); }
--- a/src/share/classes/java/util/stream/IntStream.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/IntStream.java Wed Aug 07 19:56:20 2013 -0700 @@ -517,7 +517,7 @@ long count(); /** - * Returns an {@code OptionalDouble} describing the average of elements of + * Returns an {@code OptionalDouble} describing the arithmetic mean of elements of * this stream, or an empty optional if this stream is empty. This is a * special case of a * <a href="package-summary.html#MutableReduction">reduction</a>.
--- a/src/share/classes/java/util/stream/LongPipeline.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/LongPipeline.java Wed Aug 07 19:56:20 2013 -0700 @@ -148,6 +148,7 @@ } @Override + @SuppressWarnings("unchecked") final Spliterator.OfLong lazySpliterator(Supplier<? extends Spliterator<Long>> supplier) { return new StreamSpliterators.DelegatingSpliterator.OfLong((Supplier<Spliterator.OfLong>) supplier); } @@ -209,6 +210,7 @@ Sink<Long> opWrapSink(int flags, Sink<Long> sink) { return new Sink.ChainedLong(sink) { @Override + @SuppressWarnings("unchecked") public void accept(long t) { downstream.accept(mapper.applyAsLong(t)); } @@ -226,6 +228,7 @@ Sink<Long> opWrapSink(int flags, Sink<U> sink) { return new Sink.ChainedLong(sink) { @Override + @SuppressWarnings("unchecked") public void accept(long t) { downstream.accept(mapper.apply(t)); } @@ -243,6 +246,7 @@ Sink<Long> opWrapSink(int flags, Sink<Integer> sink) { return new Sink.ChainedLong(sink) { @Override + @SuppressWarnings("unchecked") public void accept(long t) { downstream.accept(mapper.applyAsInt(t)); }
--- a/src/share/classes/java/util/stream/LongStream.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/LongStream.java Wed Aug 07 19:56:20 2013 -0700 @@ -517,7 +517,7 @@ long count(); /** - * Returns an {@code OptionalDouble} describing the average of elements of + * Returns an {@code OptionalDouble} describing the arithmetic mean of elements of * this stream, or an empty optional if this stream is empty. This is a * special case of a * <a href="package-summary.html#MutableReduction">reduction</a>.
--- a/src/share/classes/java/util/stream/MatchOps.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/MatchOps.java Wed Aug 07 19:56:20 2013 -0700 @@ -274,6 +274,7 @@ * @param <P_IN> the type of source elements for the pipeline * @param <P_OUT> the type of output elements for the pipeline */ + @SuppressWarnings("serial") private static final class MatchTask<P_IN, P_OUT> extends AbstractShortCircuitTask<P_IN, P_OUT, Boolean, MatchTask<P_IN, P_OUT>> { private final MatchOp<P_OUT> op;
--- a/src/share/classes/java/util/stream/Nodes.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/Nodes.java Wed Aug 07 19:56:20 2013 -0700 @@ -60,6 +60,7 @@ */ static final long MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + @SuppressWarnings("raw") private static final Node EMPTY_NODE = new EmptyNode.OfRef(); private static final Node.OfInt EMPTY_INT_NODE = new EmptyNode.OfInt(); private static final Node.OfLong EMPTY_LONG_NODE = new EmptyNode.OfLong(); @@ -1786,6 +1787,10 @@ } } + /* + * This and subclasses are not intended to be serializable + */ + @SuppressWarnings("serial") private static abstract class SizedCollectorTask<P_IN, P_OUT, T_SINK extends Sink<P_OUT>, K extends SizedCollectorTask<P_IN, P_OUT, T_SINK, K>> extends CountedCompleter<Void> @@ -1855,6 +1860,7 @@ fence = (int) offset + (int) length; } + @SuppressWarnings("serial") static final class OfRef<P_IN, P_OUT> extends SizedCollectorTask<P_IN, P_OUT, Sink<P_OUT>, OfRef<P_IN, P_OUT>> implements Sink<P_OUT> { @@ -1886,6 +1892,7 @@ } } + @SuppressWarnings("serial") static final class OfInt<P_IN> extends SizedCollectorTask<P_IN, Integer, Sink.OfInt, OfInt<P_IN>> implements Sink.OfInt { @@ -1917,6 +1924,7 @@ } } + @SuppressWarnings("serial") static final class OfLong<P_IN> extends SizedCollectorTask<P_IN, Long, Sink.OfLong, OfLong<P_IN>> implements Sink.OfLong { @@ -1948,6 +1956,7 @@ } } + @SuppressWarnings("serial") static final class OfDouble<P_IN> extends SizedCollectorTask<P_IN, Double, Sink.OfDouble, OfDouble<P_IN>> implements Sink.OfDouble { @@ -1980,6 +1989,7 @@ } } + @SuppressWarnings("serial") private static abstract class ToArrayTask<T, T_NODE extends Node<T>, K extends ToArrayTask<T, T_NODE, K>> extends CountedCompleter<Void> { @@ -2025,6 +2035,7 @@ } } + @SuppressWarnings("serial") private static final class OfRef<T> extends ToArrayTask<T, Node<T>, OfRef<T>> { private final T[] array; @@ -2050,6 +2061,7 @@ } } + @SuppressWarnings("serial") private static class OfPrimitive<T, T_CONS, T_ARR, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>, T_NODE extends Node.OfPrimitive<T, T_CONS, T_ARR, T_SPLITR, T_NODE>> @@ -2077,6 +2089,7 @@ } } + @SuppressWarnings("serial") private static final class OfInt extends OfPrimitive<Integer, IntConsumer, int[], Spliterator.OfInt, Node.OfInt> { private OfInt(Node.OfInt node, int[] array, int offset) { @@ -2084,6 +2097,7 @@ } } + @SuppressWarnings("serial") private static final class OfLong extends OfPrimitive<Long, LongConsumer, long[], Spliterator.OfLong, Node.OfLong> { private OfLong(Node.OfLong node, long[] array, int offset) { @@ -2091,6 +2105,7 @@ } } + @SuppressWarnings("serial") private static final class OfDouble extends OfPrimitive<Double, DoubleConsumer, double[], Spliterator.OfDouble, Node.OfDouble> { private OfDouble(Node.OfDouble node, double[] array, int offset) { @@ -2099,6 +2114,7 @@ } } + @SuppressWarnings("serial") private static class CollectorTask<P_IN, P_OUT, T_NODE extends Node<P_OUT>, T_BUILDER extends Node.Builder<P_OUT>> extends AbstractTask<P_IN, P_OUT, T_NODE, CollectorTask<P_IN, P_OUT, T_NODE, T_BUILDER>> { protected final PipelineHelper<P_OUT> helper; @@ -2135,12 +2151,13 @@ } @Override - public void onCompletion(CountedCompleter caller) { + public void onCompletion(CountedCompleter<?> caller) { if (!isLeaf()) setLocalResult(concFactory.apply(leftChild.getLocalResult(), rightChild.getLocalResult())); super.onCompletion(caller); } + @SuppressWarnings("serial") private static final class OfRef<P_IN, P_OUT> extends CollectorTask<P_IN, P_OUT, Node<P_OUT>, Node.Builder<P_OUT>> { OfRef(PipelineHelper<P_OUT> helper, @@ -2150,6 +2167,7 @@ } } + @SuppressWarnings("serial") private static final class OfInt<P_IN> extends CollectorTask<P_IN, Integer, Node.OfInt, Node.Builder.OfInt> { OfInt(PipelineHelper<Integer> helper, Spliterator<P_IN> spliterator) { @@ -2157,6 +2175,7 @@ } } + @SuppressWarnings("serial") private static final class OfLong<P_IN> extends CollectorTask<P_IN, Long, Node.OfLong, Node.Builder.OfLong> { OfLong(PipelineHelper<Long> helper, Spliterator<P_IN> spliterator) { @@ -2164,6 +2183,7 @@ } } + @SuppressWarnings("serial") private static final class OfDouble<P_IN> extends CollectorTask<P_IN, Double, Node.OfDouble, Node.Builder.OfDouble> { OfDouble(PipelineHelper<Double> helper, Spliterator<P_IN> spliterator) {
--- a/src/share/classes/java/util/stream/ReduceOps.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/ReduceOps.java Wed Aug 07 19:56:20 2013 -0700 @@ -43,7 +43,7 @@ import java.util.function.Supplier; /** - * Factory for the creating instances of {@code TerminalOp) that implement + * Factory for creating instances of {@code TerminalOp} that implement * reductions. * * @since 1.8 @@ -148,17 +148,17 @@ * reference values. * * @param <T> the type of the input elements - * @param <R> the type of the result + * @param <I> the type of the intermediate reduction result * @param collector a {@code Collector} defining the reduction * @return a {@code ReduceOp} implementing the reduction */ - public static <T,R> TerminalOp<T, R> - makeRef(Collector<? super T,R> collector) { - Supplier<R> supplier = Objects.requireNonNull(collector).resultSupplier(); - BiFunction<R, ? super T, R> accumulator = collector.accumulator(); - BinaryOperator<R> combiner = collector.combiner(); - class ReducingSink extends Box<R> - implements AccumulatingSink<T, R, ReducingSink> { + public static <T, I> TerminalOp<T, I> + makeRef(Collector<? super T, I, ?> collector) { + Supplier<I> supplier = Objects.requireNonNull(collector).supplier(); + BiConsumer<I, ? super T> accumulator = collector.accumulator(); + BinaryOperator<I> combiner = collector.combiner(); + class ReducingSink extends Box<I> + implements AccumulatingSink<T, I, ReducingSink> { @Override public void begin(long size) { state = supplier.get(); @@ -166,9 +166,7 @@ @Override public void accept(T t) { - R newResult = accumulator.apply(state, t); - if (state != newResult) - state = newResult; + accumulator.accept(state, t); } @Override @@ -176,7 +174,7 @@ state = combiner.apply(state, other.state); } } - return new ReduceOp<T, R, ReducingSink>(StreamShape.REFERENCE) { + return new ReduceOp<T, I, ReducingSink>(StreamShape.REFERENCE) { @Override public ReducingSink makeSink() { return new ReducingSink(); @@ -720,6 +718,7 @@ /** * A {@code ForkJoinTask} for performing a parallel reduce operation. */ + @SuppressWarnings("serial") private static final class ReduceTask<P_IN, P_OUT, R, S extends AccumulatingSink<P_OUT, R, S>> extends AbstractTask<P_IN, P_OUT, S, ReduceTask<P_IN, P_OUT, R, S>> { @@ -749,7 +748,7 @@ } @Override - public void onCompletion(CountedCompleter caller) { + public void onCompletion(CountedCompleter<?> caller) { if (!isLeaf()) { S leftResult = leftChild.getLocalResult(); leftResult.combine(rightChild.getLocalResult());
--- a/src/share/classes/java/util/stream/ReferencePipeline.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/ReferencePipeline.java Wed Aug 07 19:56:20 2013 -0700 @@ -170,9 +170,10 @@ } @Override + @SuppressWarnings("unchecked") public void accept(P_OUT u) { if (predicate.test(u)) - downstream.accept(u); + downstream.accept((Object) u); } }; } @@ -180,6 +181,7 @@ } @Override + @SuppressWarnings("unchecked") public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) { Objects.requireNonNull(mapper); return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE, @@ -262,6 +264,7 @@ } @Override + @SuppressWarnings("unchecked") public void accept(P_OUT u) { // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it Stream<? extends R> result = mapper.apply(u); @@ -363,6 +366,7 @@ Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) { return new Sink.ChainedReference<P_OUT>(sink) { @Override + @SuppressWarnings("unchecked") public void accept(P_OUT u) { tee.accept(u); downstream.accept(u); @@ -439,6 +443,7 @@ // The runtime type of U is never checked for equality with the component type of the runtime type of A[]. // Runtime checking will be performed when an element is stored in A[], thus if A is not a // super type of U an ArrayStoreException will be thrown. + @SuppressWarnings("rawtypes") IntFunction rawGenerator = (IntFunction) generator; return (A[]) Nodes.flatten(evaluateToArrayNode(rawGenerator), rawGenerator) .asArray(rawGenerator); @@ -490,16 +495,21 @@ } @Override - public final <R> R collect(Collector<? super P_OUT, R> collector) { + public final <R, A> R collect(Collector<? super P_OUT, A, ? extends R> collector) { + A container; if (isParallel() && (collector.characteristics().contains(Collector.Characteristics.CONCURRENT)) && (!isOrdered() || collector.characteristics().contains(Collector.Characteristics.UNORDERED))) { - R container = collector.resultSupplier().get(); - BiFunction<R, ? super P_OUT, R> accumulator = collector.accumulator(); - forEach(u -> accumulator.apply(container, u)); - return container; + container = collector.supplier().get(); + BiConsumer<A, ? super P_OUT> accumulator = collector.accumulator(); + forEach(u -> accumulator.accept(container, u)); } - return evaluate(ReduceOps.makeRef(collector)); + else { + container = evaluate(ReduceOps.makeRef(collector)); + } + return collector.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH) + ? (R) container + : collector.finisher().apply(container); } @Override
--- a/src/share/classes/java/util/stream/Sink.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/Sink.java Wed Aug 07 19:56:20 2013 -0700 @@ -242,6 +242,7 @@ * {@code accept()} method on the downstream {@code Sink}. */ static abstract class ChainedReference<T> implements Sink<T> { + @SuppressWarnings("rawtypes") protected final Sink downstream; public ChainedReference(Sink downstream) { @@ -274,6 +275,7 @@ * {@code accept()} method on the downstream {@code Sink}. */ static abstract class ChainedInt implements Sink.OfInt { + @SuppressWarnings("rawtypes") protected final Sink downstream; public ChainedInt(Sink downstream) { @@ -306,6 +308,7 @@ * {@code accept()} method on the downstream {@code Sink}. */ static abstract class ChainedLong implements Sink.OfLong { + @SuppressWarnings("rawtypes") protected final Sink downstream; public ChainedLong(Sink downstream) { @@ -338,6 +341,7 @@ * {@code accept()} method on the downstream {@code Sink}. */ static abstract class ChainedDouble implements Sink.OfDouble { + @SuppressWarnings("rawtypes") protected final Sink downstream; public ChainedDouble(Sink downstream) {
--- a/src/share/classes/java/util/stream/SliceOps.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/SliceOps.java Wed Aug 07 19:56:20 2013 -0700 @@ -550,6 +550,7 @@ * @param <P_IN> Input element type to the stream pipeline * @param <P_OUT> Output element type from the stream pipeline */ + @SuppressWarnings("serial") private static final class SliceTask<P_IN, P_OUT> extends AbstractShortCircuitTask<P_IN, P_OUT, Node<P_OUT>, SliceTask<P_IN, P_OUT>> { private final AbstractPipeline<P_OUT, P_OUT, ?> op;
--- a/src/share/classes/java/util/stream/SortedOps.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/SortedOps.java Wed Aug 07 19:56:20 2013 -0700 @@ -209,7 +209,7 @@ } @Override - public Sink<Long> opWrapSink(int flags, Sink sink) { + public Sink<Long> opWrapSink(int flags, Sink<Long> sink) { Objects.requireNonNull(sink); if (StreamOpFlag.SORTED.isKnown(flags)) @@ -248,7 +248,7 @@ } @Override - public Sink<Double> opWrapSink(int flags, Sink sink) { + public Sink<Double> opWrapSink(int flags, Sink<Double> sink) { Objects.requireNonNull(sink); if (StreamOpFlag.SORTED.isKnown(flags)) @@ -285,7 +285,7 @@ private T[] array; private int offset; - SizedRefSortingSink(Sink sink, Comparator<? super T> comparator) { + SizedRefSortingSink(Sink<T> sink, Comparator<? super T> comparator) { super(sink); this.comparator = comparator; } @@ -324,7 +324,7 @@ private final Comparator<? super T> comparator; private ArrayList<T> list; - RefSortingSink(Sink sink, Comparator<? super T> comparator) { + RefSortingSink(Sink<T> sink, Comparator<? super T> comparator) { super(sink); this.comparator = comparator; }
--- a/src/share/classes/java/util/stream/SpinedBuffer.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/SpinedBuffer.java Wed Aug 07 19:56:20 2013 -0700 @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.PrimitiveIterator; import java.util.Spliterator; import java.util.Spliterators; @@ -317,6 +318,8 @@ @Override public boolean tryAdvance(Consumer<? super E> consumer) { + Objects.requireNonNull(consumer); + if (splSpineIndex < lastSpineIndex || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) { consumer.accept(splChunk[splElementIndex++]); @@ -334,6 +337,8 @@ @Override public void forEachRemaining(Consumer<? super E> consumer) { + Objects.requireNonNull(consumer); + if (splSpineIndex < lastSpineIndex || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) { int i = splElementIndex; @@ -634,6 +639,8 @@ @Override public boolean tryAdvance(T_CONS consumer) { + Objects.requireNonNull(consumer); + if (splSpineIndex < lastSpineIndex || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) { arrayForOne(splChunk, splElementIndex++, consumer); @@ -651,6 +658,8 @@ @Override public void forEachRemaining(T_CONS consumer) { + Objects.requireNonNull(consumer); + if (splSpineIndex < lastSpineIndex || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) { int i = splElementIndex;
--- a/src/share/classes/java/util/stream/Stream.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/Stream.java Wed Aug 07 19:56:20 2013 -0700 @@ -651,12 +651,13 @@ * }</pre> * * @param <R> the type of the result + * @param <A> the intermediate accumulation type of the {@code Collector} * @param collector the {@code Collector} describing the reduction * @return the result of the reduction * @see #collect(Supplier, BiConsumer, BiConsumer) * @see Collectors */ - <R> R collect(Collector<? super T, R> collector); + <R, A> R collect(Collector<? super T, A, ? extends R> collector); /** * Returns the minimum element of this stream according to the provided @@ -827,6 +828,7 @@ * @return the new stream */ @SafeVarargs + @SuppressWarnings("varargs") // Creating a stream from an array is safe public static<T> Stream<T> of(T... values) { return Arrays.stream(values); }
--- a/src/share/classes/java/util/stream/StreamSpliterators.java Wed Aug 07 19:52:47 2013 -0700 +++ b/src/share/classes/java/util/stream/StreamSpliterators.java Wed Aug 07 19:56:20 2013 -0700 @@ -25,6 +25,7 @@ package java.util.stream; import java.util.Comparator; +import java.util.Objects; import java.util.Spliterator; import java.util.concurrent.atomic.AtomicLong; import java.util.function.BooleanSupplier; @@ -294,6 +295,7 @@ @Override public boolean tryAdvance(Consumer<? super P_OUT> consumer) { + Objects.requireNonNull(consumer); boolean hasNext = doAdvance(); if (hasNext) consumer.accept(buffer.get(nextToConsume)); @@ -303,6 +305,7 @@ @Override public void forEachRemaining(Consumer<? super P_OUT> consumer) { if (buffer == null && !finished) { + Objects.requireNonNull(consumer); init(); ph.wrapAndCopyInto((Sink<P_OUT>) consumer::accept, spliterator); @@ -350,6 +353,7 @@ @Override public boolean tryAdvance(IntConsumer consumer) { + Objects.requireNonNull(consumer); boolean hasNext = doAdvance(); if (hasNext) consumer.accept(buffer.get(nextToConsume)); @@ -359,6 +363,7 @@ @Override public void forEachRemaining(IntConsumer consumer) { if (buffer == null && !finished) { + Objects.requireNonNull(consumer); init(); ph.wrapAndCopyInto((Sink.OfInt) consumer::accept, spliterator); @@ -406,6 +411,7 @@ @Override public boolean tryAdvance(LongConsumer consumer) { + Objects.requireNonNull(consumer); boolean hasNext = doAdvance(); if (hasNext) consumer.accept(buffer.get(nextToConsume)); @@ -415,6 +421,7 @@ @Override public void forEachRemaining(LongConsumer consumer) { if (buffer == null && !finished) { + Objects.requireNonNull(consumer); init(); ph.wrapAndCopyInto((Sink.OfLong) consumer::accept, spliterator); @@ -462,6 +469,7 @@ @Override public boolean tryAdvance(DoubleConsumer consumer) { + Objects.requireNonNull(consumer); boolean hasNext = doAdvance(); if (hasNext) consumer.accept(buffer.get(nextToConsume)); @@ -471,6 +479,7 @@ @Override public void forEachRemaining(DoubleConsumer consumer) { if (buffer == null && !finished) { + Objects.requireNonNull(consumer); init(); ph.wrapAndCopyInto((Sink.OfDouble) consumer::accept, spliterator); @@ -696,6 +705,8 @@ @Override public boolean tryAdvance(Consumer<? super T> action) { + Objects.requireNonNull(action); + if (sliceOrigin >= fence) return false; @@ -713,6 +724,8 @@ @Override public void forEachRemaining(Consumer<? super T> action) { + Objects.requireNonNull(action); + if (sliceOrigin >= fence) return; @@ -754,6 +767,8 @@ @Override public boolean tryAdvance(T_CONS action) { + Objects.requireNonNull(action); + if (sliceOrigin >= fence) return false; @@ -771,6 +786,8 @@ @Override public void forEachRemaining(T_CONS action) { + Objects.requireNonNull(action); + if (sliceOrigin >= fence) return; @@ -895,7 +912,8 @@ this.permits = new AtomicLong(limit >= 0 ? skip + limit : skip); } - UnorderedSliceSpliterator(T_SPLITR s, UnorderedSliceSpliterator parent) { + UnorderedSliceSpliterator(T_SPLITR s, + UnorderedSliceSpliterator<T, T_SPLITR> parent) { this.s = s; this.unlimited = parent.unlimited; this.permits = parent.permits; @@ -974,7 +992,7 @@ super(s, skip, limit); } - OfRef(Spliterator<T> s, OfRef parent) { + OfRef(Spliterator<T> s, OfRef<T> parent) { super(s, parent); } @@ -985,6 +1003,8 @@ @Override public boolean tryAdvance(Consumer<? super T> action) { + Objects.requireNonNull(action); + while (permitStatus() != PermitStatus.NO_MORE) { if (!s.tryAdvance(this)) return false; @@ -999,6 +1019,8 @@ @Override public void forEachRemaining(Consumer<? super T> action) { + Objects.requireNonNull(action); + ArrayBuffer.OfRef<T> sb = null; PermitStatus permitStatus; while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) { @@ -1051,6 +1073,8 @@ @Override public boolean tryAdvance(T_CONS action) { + Objects.requireNonNull(action); + while (permitStatus() != PermitStatus.NO_MORE) { if (!s.tryAdvance((T_CONS) this)) return false; @@ -1066,6 +1090,8 @@ @Override