提交 e5c0b05d 编写于 作者: L lana

Merge

......@@ -212,3 +212,5 @@ d5228e624826a10ccc5b05f30ad8d839b58fe48d jdk8-b87
8dbb4b159e04de3c447c9242c70505e71f8624c7 jdk8-b88
845025546e35519fbb8970e79fc2a834063a5e19 jdk8-b89
c63eda8f63008a4398d2c22ac8d72f7fef6f9238 jdk8-b90
169451cf0cc53bde5af24f9820ea3f35ec4b4df4 jdk8-b91
a2a2a91075ad85becbe10a39d7fd04ef9bea8df5 jdk8-b92
......@@ -171,3 +171,13 @@ FILES_NO_MOTIF_c = \
GLXSurfaceData.c \
AccelGlyphCache.c \
CUPSfuncs.c
ifeq ($(PLATFORM), macosx)
FILES_NO_MOTIF_objc = \
AWTFont.m \
AWTStrike.m \
CCharToGlyphMapper.m \
CGGlyphImages.m \
CGGlyphOutlines.m \
CoreTextSupport.m
endif # PLATFORM
......@@ -187,3 +187,14 @@ FILES_export2 = \
java/awt/dnd/DnDConstants.java \
sun/awt/CausedFocusEvent.java
ifeq ($(PLATFORM), macosx)
ifeq ($(HEADLESS), true)
FILES_export += \
sun/awt/SunHints.java \
sun/font/CCharToGlyphMapper.java \
sun/font/CFont.java \
sun/font/CFontManager.java \
sun/font/CStrike.java \
sun/font/CStrikeDisposer.java
endif # HEADLESS
endif # PLATFORM
......@@ -43,6 +43,10 @@ include $(BUILDDIR)/sun/awt/FILES_export_unix.gmk
# compiled based on the motif version.
FILES_c = $(FILES_NO_MOTIF_c)
ifeq ($(PLATFORM), macosx)
FILES_objc = $(FILES_NO_MOTIF_objc)
endif # PLATFORM
ifeq ($(PLATFORM), solaris)
ifneq ($(ARCH), amd64)
FILES_reorder += reorder-$(ARCH)
......@@ -97,6 +101,10 @@ vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/../java2d/pipe
vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR)/image
vpath %.c $(PLATFORM_SRC)/native/$(PKGDIR)/robot_child
ifeq ($(PLATFORM), macosx)
vpath %.m $(call NativeSrcDirList,,native/sun/font)
endif # PLATFORM
#
# Libraries to link in.
#
......@@ -192,13 +200,21 @@ CPPFLAGS += -I$(SHARE_SRC)/native/$(PKGDIR)/debug \
$(EVENT_MODEL)
ifeq ($(PLATFORM), macosx)
CPPFLAGS += -I$(CUPS_HEADERS_PATH)
CPPFLAGS += -I$(CUPS_HEADERS_PATH) \
$(call NativeSrcDirList,-I,native/sun/awt) \
$(call NativeSrcDirList,-I,native/sun/font)
ifndef HEADLESS
CPPFLAGS += -I$(MOTIF_DIR)/include \
-I$(OPENWIN_HOME)/include
LDFLAGS += -L$(MOTIF_LIB) -L$(OPENWIN_LIB)
else
LDFLAGS += -framework Accelerate \
-framework ApplicationServices \
-framework Cocoa \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation \
-framework JavaRuntimeSupport
endif # !HEADLESS
endif # PLATFORM
......
......@@ -2314,6 +2314,10 @@ LIBAWT_HEADLESS_DIRS:=$(JDK_TOPDIR)/src/share/native/sun/font \
$(JDK_TOPDIR)/src/solaris/native/sun/java2d/opengl \
$(JDK_TOPDIR)/src/solaris/native/sun/java2d/x11
ifeq ($(OPENJDK_TARGET_OS),macosx)
LIBAWT_HEADLESS_DIRS+=$(JDK_TOPDIR)/src/macosx/native/sun/font
endif
LIBAWT_HEADLESS_CFLAGS:=-DHEADLESS=true \
-DX11_PATH=\"$(X11_PATH)\" -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
$(CUPS_CFLAGS) \
......@@ -2328,6 +2332,12 @@ LIBAWT_HEADLESS_CFLAGS:=-DHEADLESS=true \
-I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/jdga \
$(foreach dir,$(LIBAWT_HEADLESS_DIRS),-I$(dir))
ifeq ($(OPENJDK_TARGET_OS),macosx)
LIBAWT_HEADLESS_CFLAGS+=\
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks
endif
LIBAWT_HEADLESS_FILES:=\
awt_Font.c \
HeadlessToolkit.c \
......@@ -2356,6 +2366,16 @@ LIBAWT_HEADLESS_FILES:=\
AccelGlyphCache.c \
CUPSfuncs.c
ifeq ($(OPENJDK_TARGET_OS),macosx)
LIBAWT_HEADLESS_FILES+=\
AWTFont.m \
AWTStrike.m \
CCharToGlyphMapper.m \
CGGlyphImages.m \
CGGlyphOutlines.m \
CoreTextSupport.m
endif
LIBAWT_HEADLESS_REORDER:=
ifeq ($(OPENJDK_TARGET_OS), solaris)
ifneq ($(OPENJDK_TARGET_CPU), x86_64)
......@@ -2382,7 +2402,13 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBAWT_HEADLESS,\
REORDER:=$(LIBAWT_HEADLESS_REORDER), \
LDFLAGS_SUFFIX_linux:=-ljvm -lawt -lm $(LIBDL) -ljava,\
LDFLAGS_SUFFIX_solaris:=$(LIBDL) -ljvm -lawt -lm -ljava $(LIBCXX) -lc,\
LDFLAGS_SUFFIX_macosx:=-ljvm $(LIBCXX) -lawt $(LIBDL) -ljava,\
LDFLAGS_SUFFIX_macosx:=-ljvm $(LIBCXX) -lawt $(LIBDL) -ljava \
-framework Accelerate \
-framework ApplicationServices \
-framework Cocoa \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation \
-framework JavaRuntimeSupport,\
OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/libawt_headless,\
DEBUG_SYMBOLS:=$(DEBUG_ALL_BINARIES)))
......
......@@ -36,6 +36,7 @@ import java.security.PrivilegedAction;
import javax.print.*;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.standard.PageRanges;
import sun.java2d.*;
import sun.print.*;
......@@ -173,6 +174,19 @@ public class CPrinterJob extends RasterPrinterJob {
if (nsPrintInfo != null) {
fNSPrintInfo = nsPrintInfo.getValue();
}
PageRanges pageRangesAttr = (PageRanges)attributes.get(PageRanges.class);
if (isSupportedValue(pageRangesAttr, attributes)) {
SunPageSelection rangeSelect = (SunPageSelection)attributes.get(SunPageSelection.class);
// If rangeSelect is not null, we are using AWT's print dialog that has
// All, Selection, and Range radio buttons
if (rangeSelect == null || rangeSelect == SunPageSelection.RANGE) {
int[][] range = pageRangesAttr.getMembers();
// setPageRange will set firstPage and lastPage as called in getFirstPage
// and getLastPage
setPageRange(range[0][0] - 1, range[0][1] - 1);
}
}
}
volatile boolean onEventThread;
......@@ -225,7 +239,6 @@ public class CPrinterJob extends RasterPrinterJob {
* the end of the document. Note that firstPage
* and lastPage are 0 based page indices.
*/
int numPages = mDocument.getNumberOfPages();
int firstPage = getFirstPage();
int lastPage = getLastPage();
......@@ -242,42 +255,53 @@ public class CPrinterJob extends RasterPrinterJob {
userCancelled = false;
}
if (EventQueue.isDispatchThread()) {
// This is an AWT EventQueue, and this print rendering loop needs to block it.
//Add support for PageRange
PageRanges pr = (attributes == null) ? null
: (PageRanges)attributes.get(PageRanges.class);
int[][] prMembers = (pr == null) ? new int[0][0] : pr.getMembers();
int loopi = 0;
do {
if (EventQueue.isDispatchThread()) {
// This is an AWT EventQueue, and this print rendering loop needs to block it.
onEventThread = true;
printingLoop = AccessController.doPrivileged(new PrivilegedAction<SecondaryLoop>() {
@Override
public SecondaryLoop run() {
return Toolkit.getDefaultToolkit()
.getSystemEventQueue()
.createSecondaryLoop();
}
});
onEventThread = true;
printingLoop = AccessController.doPrivileged(new PrivilegedAction<SecondaryLoop>() {
@Override
public SecondaryLoop run() {
return Toolkit.getDefaultToolkit()
.getSystemEventQueue()
.createSecondaryLoop();
try {
// Fire off the print rendering loop on the AppKit thread, and don't have
// it wait and block this thread.
if (printLoop(false, firstPage, lastPage)) {
// Start a secondary loop on EDT until printing operation is finished or cancelled
printingLoop.enter();
}
} catch (Exception e) {
e.printStackTrace();
}
});
} else {
// Fire off the print rendering loop on the AppKit, and block this thread
// until it is done.
// But don't actually block... we need to come back here!
onEventThread = false;
try {
// Fire off the print rendering loop on the AppKit thread, and don't have
// it wait and block this thread.
if (printLoop(false, firstPage, lastPage)) {
// Start a secondary loop on EDT until printing operation is finished or cancelled
printingLoop.enter();
try {
printLoop(true, firstPage, lastPage);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
// Fire off the print rendering loop on the AppKit, and block this thread
// until it is done.
// But don't actually block... we need to come back here!
onEventThread = false;
try {
printLoop(true, firstPage, lastPage);
} catch (Exception e) {
e.printStackTrace();
if (++loopi < prMembers.length) {
firstPage = prMembers[loopi][0]-1;
lastPage = prMembers[loopi][1] -1;
}
}
} while (loopi < prMembers.length);
} finally {
synchronized (this) {
// NOTE: Native code shouldn't allow exceptions out while
......
......@@ -395,6 +395,7 @@ JNF_COCOA_EXIT(env);
#pragma mark --- Miscellaneous JNI ---
#ifndef HEADLESS
/*
* Class: sun_awt_PlatformFont
* Method: initIDs
......@@ -416,3 +417,4 @@ Java_sun_awt_FontDescriptor_initIDs
(JNIEnv *env, jclass cls)
{
}
#endif
/*
* 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
......@@ -90,14 +90,16 @@ public class Continuation extends ResolveResult {
* Constructs a new instance of Continuation.
* @param top The name of the object that is to be resolved/operated upon.
* This becomes the Continuation's 'starter' and is used to
* calculate the "resolved name" when filling in a NamingException.
* calculate the "resolved name" when filling in a NamingException.
* @param environment The environment used by the caller. It is used
* when setting the "environment" of a CannotProceedException.
* when setting the "environment" of a CannotProceedException.
*/
@SuppressWarnings("unchecked") // For Hashtable clone: environment.clone()
public Continuation(Name top, Hashtable<?,?> environment) {
super();
starter = top;
this.environment = environment;
this.environment = (Hashtable<?,?>)
((environment == null) ? null : environment.clone());
}
/**
......
/*
* 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
......@@ -69,6 +69,7 @@ final public class LazySearchEnumerationImpl
}
}
@SuppressWarnings("unchecked") // For Hashtable clone: env.clone()
public LazySearchEnumerationImpl(NamingEnumeration<Binding> candidates,
AttrFilter filter, SearchControls cons,
Context ctx, Hashtable<String, Object> env, boolean useFactory)
......@@ -76,7 +77,8 @@ final public class LazySearchEnumerationImpl
this.candidates = candidates;
this.filter = filter;
this.env = env;
this.env = (Hashtable<String, Object>)
((env == null) ? null : env.clone());
this.context = ctx;
this.useFactory = useFactory;
......
/*
* 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
......@@ -53,7 +53,8 @@ abstract public class GenericURLContext implements Context {
@SuppressWarnings("unchecked") // Expect Hashtable<String, Object>
public GenericURLContext(Hashtable<?,?> env) {
// context that is not tied to any specific URL
myEnv = (Hashtable<String, Object>)env; // copied on write
myEnv =
(Hashtable<String, Object>)(env == null ? null : env.clone());
}
public void close() throws NamingException {
......@@ -488,22 +489,19 @@ abstract public class GenericURLContext implements Context {
return result;
}
@SuppressWarnings("unchecked") // clone()
public Object removeFromEnvironment(String propName)
throws NamingException {
if (myEnv == null) {
return null;
}
myEnv = (Hashtable<String, Object>)myEnv.clone();
return myEnv.remove(propName);
}
@SuppressWarnings("unchecked") // clone()
public Object addToEnvironment(String propName, Object propVal)
throws NamingException {
myEnv = (myEnv == null)
? new Hashtable<String, Object>(11, 0.75f)
: (Hashtable<String, Object>)myEnv.clone();
if (myEnv == null) {
myEnv = new Hashtable<String, Object>(11, 0.75f);
}
return myEnv.put(propName, propVal);
}
......
......@@ -240,13 +240,15 @@ class FileInputStream extends InputStream
*
* <p>The <code>skip</code> method may, for a variety of
* reasons, end up skipping over some smaller number of bytes,
* possibly <code>0</code>. If <code>n</code> is negative, an
* <code>IOException</code> is thrown, even though the <code>skip</code>
* method of the {@link InputStream} superclass does nothing in this case.
* The actual number of bytes skipped is returned.
* possibly <code>0</code>. If <code>n</code> is negative, the method
* will try to skip backwards. In case the backing file does not support
* backward skip at its current position, an <code>IOException</code> is
* thrown. The actual number of bytes skipped is returned. If it skips
* forwards, it returns a positive value. If it skips backwards, it
* returns a negative value.
*
* <p>This method may skip more bytes than are remaining in the backing
* file. This produces no exception and the number of bytes skipped
* <p>This method may skip more bytes than what are remaining in the
* backing file. This produces no exception and the number of bytes skipped
* may include some number of bytes that were beyond the EOF of the
* backing file. Attempting to read from the stream after skipping past
* the end will result in -1 indicating the end of the file.
......@@ -261,9 +263,10 @@ class FileInputStream extends InputStream
/**
* Returns an estimate of the number of remaining bytes that can be read (or
* skipped over) from this input stream without blocking by the next
* invocation of a method for this input stream. The next invocation might be
* the same thread or another thread. A single read or skip of this
* many bytes will not block, but may read or skip fewer bytes.
* invocation of a method for this input stream. Returns 0 when the file
* position is beyond EOF. The next invocation might be the same thread
* or another thread. A single read or skip of this many bytes will not
* block, but may read or skip fewer bytes.
*
* <p> In some cases, a non-blocking read (or skip) may appear to be
* blocked when it is merely slow, for example when reading large
......
/*
* Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 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
......@@ -193,8 +193,10 @@ public abstract class InputStream implements Closeable {
* up skipping over some smaller number of bytes, possibly <code>0</code>.
* This may result from any of a number of conditions; reaching end of file
* before <code>n</code> bytes have been skipped is only one possibility.
* The actual number of bytes skipped is returned. If <code>n</code> is
* negative, no bytes are skipped.
* The actual number of bytes skipped is returned. If {@code n} is
* negative, the {@code skip} method for class {@code InputStream} always
* returns 0, and no bytes are skipped. Subclasses may handle the negative
* value differently.
*
* <p> The <code>skip</code> method of this class creates a
* byte array and then repeatedly reads into it until <code>n</code> bytes
......
......@@ -28,6 +28,7 @@ package java.lang;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;
import java.lang.reflect.Field;
import java.lang.reflect.Executable;
......@@ -115,9 +116,9 @@ import sun.reflect.misc.ReflectUtil;
* @since JDK1.0
*/
public final class Class<T> implements java.io.Serializable,
java.lang.reflect.GenericDeclaration,
java.lang.reflect.Type,
java.lang.reflect.AnnotatedElement {
GenericDeclaration,
Type,
AnnotatedElement {
private static final int ANNOTATION= 0x00002000;
private static final int ENUM = 0x00004000;
private static final int SYNTHETIC = 0x00001000;
......@@ -3182,7 +3183,7 @@ public final class Class<T> implements java.io.Serializable,
*/
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return AnnotatedElement.super.isAnnotationPresent(annotationClass);
return GenericDeclaration.super.isAnnotationPresent(annotationClass);
}
/**
......
......@@ -1010,13 +1010,14 @@ public final class String
private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
char v1[] = value;
char v2[] = sb.getValue();
int i = 0;
int n = value.length;
while (n-- != 0) {
int n = v1.length;
if (n != sb.length()) {
return false;
}
for (int i = 0; i < n; i++) {
if (v1[i] != v2[i]) {
return false;
}
i++;
}
return true;
}
......@@ -1038,8 +1039,6 @@ public final class String
* @since 1.5
*/
public boolean contentEquals(CharSequence cs) {
if (value.length != cs.length())
return false;
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
......@@ -1055,12 +1054,14 @@ public final class String
return true;
// Argument is a generic CharSequence
char v1[] = value;
int i = 0;
int n = value.length;
while (n-- != 0) {
if (v1[i] != cs.charAt(i))
int n = v1.length;
if (n != cs.length()) {
return false;
}
for (int i = 0; i < n; i++) {
if (v1[i] != cs.charAt(i)) {
return false;
i++;
}
}
return true;
}
......
......@@ -335,10 +335,8 @@ import java.util.Arrays;
* @since 1.5
*/
@Override
public StringBuffer append(CharSequence s) {
// Note, synchronization achieved via invocations of other StringBuffer methods after
// narrowing of s to specific type
// Ditto for toStringCache clearing
public synchronized StringBuffer append(CharSequence s) {
toStringCache = null;
super.append(s);
return this;
}
......
......@@ -145,10 +145,10 @@ class Thread implements Runnable {
registerNatives();
}
private char name[];
private int priority;
private Thread threadQ;
private long eetop;
private volatile char name[];
private int priority;
private Thread threadQ;
private long eetop;
/* Whether or not to single_step this thread. */
private boolean single_step;
......@@ -1135,7 +1135,7 @@ class Thread implements Runnable {
* @see #getName
* @see #checkAccess()
*/
public final void setName(String name) {
public final synchronized void setName(String name) {
checkAccess();
this.name = name.toCharArray();
if (threadStatus != 0) {
......@@ -1150,7 +1150,7 @@ class Thread implements Runnable {
* @see #setName(String)
*/
public final String getName() {
return String.valueOf(name);
return new String(name, true);
}
/**
......
/*
* Copyright (c) 1997, 2011, 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
......@@ -138,8 +138,23 @@ public abstract class Reference<T> {
pending = r.discovered;
r.discovered = null;
} else {
// The waiting on the lock may cause an OOME because it may try to allocate
// exception objects, so also catch OOME here to avoid silent exit of the
// reference handler thread.
//
// Explicitly define the order of the two exceptions we catch here
// when waiting for the lock.
//
// We do not want to try to potentially load the InterruptedException class
// (which would be done if this was its first use, and InterruptedException
// were checked first) in this situation.
//
// This may lead to the VM not ever trying to load the InterruptedException
// class again.
try {
lock.wait();
try {
lock.wait();
} catch (OutOfMemoryError x) { }
} catch (InterruptedException x) { }
continue;
}
......
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -30,7 +30,7 @@ package java.lang.reflect;
*
* @since 1.5
*/
public interface GenericDeclaration {
public interface GenericDeclaration extends AnnotatedElement {
/**
* Returns an array of {@code TypeVariable} objects that
* represent the type variables declared by the generic
......
......@@ -34,6 +34,7 @@ import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.lang.ref.WeakReference;
import java.nio.charset.CoderMalfunctionError; // javadoc
import java.util.Arrays;
/**
......@@ -244,7 +245,12 @@ public abstract class Charset$Coder$ {
* which is never <tt>null</tt> and is never empty
*/
public final $replType$ replacement() {
#if[decoder]
return replacement;
#end[decoder]
#if[encoder]
return Arrays.copyOf(replacement, replacement.$replLength$);
#end[encoder]
}
/**
......@@ -280,12 +286,15 @@ public abstract class Charset$Coder$ {
throw new IllegalArgumentException("Empty replacement");
if (len > max$ItypesPerOtype$)
throw new IllegalArgumentException("Replacement too long");
#if[decoder]
this.replacement = newReplacement;
#end[decoder]
#if[encoder]
if (!isLegalReplacement(newReplacement))
throw new IllegalArgumentException("Illegal replacement");
this.replacement = Arrays.copyOf(newReplacement, newReplacement.$replLength$);
#end[encoder]
this.replacement = newReplacement;
implReplaceWith(newReplacement);
implReplaceWith(this.replacement);
return this;
}
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.nio.file;
import java.io.Closeable;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.nio.file.FileTreeWalker.Event;
/**
* An {@code Iterator to iterate over the nodes of a file tree.
*
* <pre>{@code
* try (FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options)) {
* while (iterator.hasNext()) {
* Event ev = iterator.next();
* Path path = ev.file();
* BasicFileAttributes attrs = ev.attributes();
* }
* }
* }</pre>
*/
class FileTreeIterator implements Iterator<Event>, Closeable {
private final FileTreeWalker walker;
private Event next;
/**
* Creates a new iterator to walk the file tree starting at the given file.
*
* @throws IllegalArgumentException
* if {@code maxDepth} is negative
* @throws IOException
* if an I/O errors occurs opening the starting file
* @throws SecurityException
* if the security manager denies access to the starting file
* @throws NullPointerException
* if {@code start} or {@code options} is {@ocde null} or
* the options array contains a {@code null} element
*/
FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)
throws IOException
{
this.walker = new FileTreeWalker(Arrays.asList(options), maxDepth);
this.next = walker.walk(start);
assert next.type() == FileTreeWalker.EventType.ENTRY ||
next.type() == FileTreeWalker.EventType.START_DIRECTORY;
// IOException if there a problem accessing the starting file
IOException ioe = next.ioeException();
if (ioe != null)
throw ioe;
}
private void fetchNextIfNeeded() {
if (next == null) {
FileTreeWalker.Event ev = walker.next();
while (ev != null) {
IOException ioe = ev.ioeException();
if (ioe != null)
throw new UncheckedIOException(ioe);
// END_DIRECTORY events are ignored
if (ev.type() != FileTreeWalker.EventType.END_DIRECTORY) {
next = ev;
return;
}
ev = walker.next();
}
}
}
@Override
public boolean hasNext() {
if (!walker.isOpen())
throw new IllegalStateException();
fetchNextIfNeeded();
return next != null;
}
@Override
public Event next() {
if (!walker.isOpen())
throw new IllegalStateException();
fetchNextIfNeeded();
if (next == null)
throw new NoSuchElementException();
Event result = next;
next = null;
return result;
}
@Override
public void close() {
walker.close();
}
}
......@@ -29,8 +29,8 @@ import java.nio.file.attribute.BasicFileAttributes;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import sun.nio.fs.BasicFileAttributesHolder;
/**
......@@ -164,8 +164,17 @@ class FileTreeWalker implements Closeable {
/**
* Creates a {@code FileTreeWalker}.
*
* @throws IllegalArgumentException
* if {@code maxDepth} is negative
* @throws ClassCastException
* if (@code options} contains an element that is not a
* {@code FileVisitOption}
* @throws NullPointerException
* if {@code options} is {@ocde null} or the options
* array contains a {@code null} element
*/
FileTreeWalker(Set<FileVisitOption> options, int maxDepth) {
FileTreeWalker(Collection<FileVisitOption> options, int maxDepth) {
boolean fl = false;
for (FileVisitOption option: options) {
// will throw NPE if options contains null
......@@ -175,6 +184,9 @@ class FileTreeWalker implements Closeable {
throw new AssertionError("Should not get here");
}
}
if (maxDepth < 0)
throw new IllegalArgumentException("'maxDepth' is negative");
this.followLinks = fl;
this.linkOptions = (fl) ? new LinkOption[0] :
new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
......
......@@ -25,10 +25,13 @@
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.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.io.Closeable;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
......@@ -38,7 +41,13 @@ import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.*;
import java.util.function.BiPredicate;
import java.util.stream.CloseableStream;
import java.util.stream.DelegatingStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.nio.charset.Charset;
......@@ -2587,9 +2596,6 @@ public final class Files {
FileVisitor<? super Path> visitor)
throws IOException
{
if (maxDepth < 0)
throw new IllegalArgumentException("'maxDepth' is negative");
/**
* Create a FileTreeWalker to walk the file tree, invoking the visitor
* for each event.
......@@ -2940,40 +2946,6 @@ public final class Files {
}
}
/**
* Read all the bytes from an input stream. The {@code initialSize}
* parameter indicates the initial size of the byte[] to allocate.
*/
private static byte[] read(InputStream source, int initialSize)
throws IOException
{
int capacity = initialSize;
byte[] buf = new byte[capacity];
int nread = 0;
int rem = buf.length;
int n;
// 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, rem)) > 0) {
nread += n;
rem -= n;
assert rem >= 0;
if (rem == 0) {
// need larger buffer
int newCapacity = capacity << 1;
if (newCapacity < 0) {
if (capacity == Integer.MAX_VALUE)
throw new OutOfMemoryError("Required array size too large");
newCapacity = Integer.MAX_VALUE;
}
rem = newCapacity - capacity;
buf = Arrays.copyOf(buf, newCapacity);
capacity = newCapacity;
}
}
return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
}
/**
* Read 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
......@@ -2999,12 +2971,22 @@ public final class Files {
* method is invoked to check read access to the file.
*/
public static byte[] readAllBytes(Path path) throws IOException {
long size = size(path);
if (size > (long)Integer.MAX_VALUE)
throw new OutOfMemoryError("Required array size too large");
try (FileChannel fc = FileChannel.open(path)) {
long size = fc.size();
if (size > (long)Integer.MAX_VALUE)
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;
}
}
try (InputStream in = newInputStream(path)) {
return read(in, (int)size);
int nread = bb.position();
return (nread == size) ? arr : Arrays.copyOf(arr, nread);
}
}
......@@ -3177,4 +3159,336 @@ public final class Files {
}
return path;
}
// -- Stream APIs --
/**
* Implementation of CloseableStream
*/
private static class DelegatingCloseableStream<T> extends DelegatingStream<T>
implements CloseableStream<T>
{
private final Closeable closeable;
DelegatingCloseableStream(Closeable c, Stream<T> delegate) {
super(delegate);
this.closeable = c;
}
public void close() {
try {
closeable.close();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
}
/**
* Return a lazily populated {@code CloseableStream}, the elements of
* which are the entries in the directory. The listing is not recursive.
*
* <p> The elements of the stream are {@link Path} objects that are
* obtained as if by {@link Path#resolve(Path) resolving} the name of the
* directory entry against {@code dir}. Some file systems maintain special
* links to the directory itself and the directory's parent directory.
* Entries representing these links are not included.
*
* <p> The stream is <i>weakly consistent</i>. It is thread safe but does
* not freeze the directory while iterating, so it may (or may not)
* reflect updates to the directory that occur after returning from this
* method.
*
* <p> When not using the try-with-resources construct, then the stream's
* {@link CloseableStream#close close} method should be invoked after the
* operation is completed so as to free any resources held for the open
* directory. Operating on a closed stream behaves as if the end of stream
* has been reached. Due to read-ahead, one or more elements may be
* returned after the stream has been closed.
*
* <p> If an {@link IOException} is thrown when accessing the directory
* after this method has returned, it is wrapped in an {@link
* UncheckedIOException} which will be thrown from the method that caused
* the access to take place.
*
* @param dir The path to the directory
*
* @return The {@code CloseableStream} describing the content of the
* directory
*
* @throws NotDirectoryException
* if the file could not otherwise be opened because it is not
* a directory <i>(optional specific exception)</i>
* @throws IOException
* if an I/O error occurs when opening the directory
* @throws SecurityException
* In the case of the default provider, and a security manager is
* installed, the {@link SecurityManager#checkRead(String) checkRead}
* method is invoked to check read access to the directory.
*
* @see #newDirectoryStream(Path)
* @since 1.8
*/
public static CloseableStream<Path> list(Path dir) throws IOException {
DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
final Iterator<Path> delegate = ds.iterator();
// Re-wrap DirectoryIteratorException to UncheckedIOException
Iterator<Path> it = new Iterator<Path>() {
public boolean hasNext() {
try {
return delegate.hasNext();
} catch (DirectoryIteratorException e) {
throw new UncheckedIOException(e.getCause());
}
}
public Path next() {
try {
return delegate.next();
} catch (DirectoryIteratorException e) {
throw new UncheckedIOException(e.getCause());
}
}
};
return new DelegatingCloseableStream<>(ds,
StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,
Spliterator.DISTINCT)));
}
/**
* Return a {@code CloseableStream} that is lazily populated with {@code
* Path} by walking the file tree rooted at a given starting file. The
* file tree is traversed <em>depth-first</em>, the elements in the stream
* are {@link Path} objects that are obtained as if by {@link
* Path#resolve(Path) resolving} the relative path against {@code start}.
*
* <p> The {@code stream} walks the file tree as elements are consumed.
* The {@code CloseableStream} returned is guaranteed to have at least one
* element, the starting file itself. For each file visited, the stream
* attempts to read its {@link BasicFileAttributes}. If the file is a
* directory and can be opened successfully, entries in the directory, and
* their <em>descendants</em> will follow the directory in the stream as
* they are encountered. When all entries have been visited, then the
* directory is closed. The file tree walk then continues at the next
* <em>sibling</em> of the directory.
*
* <p> The stream is <i>weakly consistent</i>. It does not freeze the
* file tree while iterating, so it may (or may not) reflect updates to
* the file tree that occur after returned from this method.
*
* <p> By default, symbolic links are not automatically followed by this
* method. If the {@code options} parameter contains the {@link
* FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
* followed. When following links, and the attributes of the target cannot
* be read, then this method attempts to get the {@code BasicFileAttributes}
* of the link.
*
* <p> If the {@code options} parameter contains the {@link
* FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
* track of directories visited so that cycles can be detected. A cycle
* arises when there is an entry in a directory that is an ancestor of the
* directory. Cycle detection is done by recording the {@link
* java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
* or if file keys are not available, by invoking the {@link #isSameFile
* isSameFile} method to test if a directory is the same file as an
* ancestor. When a cycle is detected it is treated as an I/O error with
* an instance of {@link FileSystemLoopException}.
*
* <p> The {@code maxDepth} parameter is the maximum number of levels of
* directories to visit. A value of {@code 0} means that only the starting
* file is visited, unless denied by the security manager. A value of
* {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
* levels should be visited.
*
* <p> When a security manager is installed and it denies access to a file
* (or directory), then it is ignored and not included in the stream.
*
* <p> When not using the try-with-resources construct, then the stream's
* {@link CloseableStream#close close} method should be invoked after the
* operation is completed so as to free any resources held for the open
* directory. Operate the stream after it is closed will throw an
* {@link java.lang.IllegalStateException}.
*
* <p> If an {@link IOException} is thrown when accessing the directory
* after this method has returned, it is wrapped in an {@link
* UncheckedIOException} which will be thrown from the method that caused
* the access to take place.
*
* @param start
* the starting file
* @param maxDepth
* the maximum number of directory levels to visit
* @param options
* options to configure the traversal
*
* @return the {@link CloseableStream} of {@link Path}
*
* @throws IllegalArgumentException
* if the {@code maxDepth} parameter is negative
* @throws SecurityException
* If the security manager denies access to the starting file.
* In the case of the default provider, the {@link
* SecurityManager#checkRead(String) checkRead} method is invoked
* to check read access to the directory.
* @throws IOException
* if an I/O error is thrown when accessing the starting file.
* @since 1.8
*/
public static CloseableStream<Path> walk(Path start, int maxDepth,
FileVisitOption... options)
throws IOException
{
FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
return new DelegatingCloseableStream<>(iterator,
StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
.map(entry -> entry.file()));
}
/**
* Return a {@code CloseableStream} that is lazily populated with {@code
* Path} by walking the file tree rooted at a given starting file. The
* file tree is traversed <em>depth-first</em>, the elements in the stream
* are {@link Path} objects that are obtained as if by {@link
* Path#resolve(Path) resolving} the relative path against {@code start}.
*
* <p> This method works as if invoking it were equivalent to evaluating the
* expression:
* <blockquote><pre>
* walk(start, Integer.MAX_VALUE, options)
* </pre></blockquote>
* In other words, it visits all levels of the file tree.
*
* @param start
* the starting file
* @param options
* options to configure the traversal
*
* @return the {@link CloseableStream} of {@link Path}
*
* @throws SecurityException
* If the security manager denies access to the starting file.
* In the case of the default provider, the {@link
* SecurityManager#checkRead(String) checkRead} method is invoked
* to check read access to the directory.
* @throws IOException
* if an I/O error is thrown when accessing the starting file.
*
* @see #walk(Path, int, FileVisitOption...)
* @since 1.8
*/
public static CloseableStream<Path> walk(Path start,
FileVisitOption... options)
throws IOException
{
return walk(start, Integer.MAX_VALUE, options);
}
/**
* Return a {@code CloseableStream} that is lazily populated with {@code
* Path} by searching for files in a file tree rooted at a given starting
* file.
*
* <p> This method walks the file tree in exactly the manner specified by
* the {@link #walk walk} method. For each file encountered, the given
* {@link BiPredicate} is invoked with its {@link Path} and {@link
* BasicFileAttributes}. The {@code Path} object is obtained as if by
* {@link Path#resolve(Path) resolving} the relative path against {@code
* start} and is only included in the returned {@link CloseableStream} if
* the {@code BiPredicate} returns true. Compare to calling {@link
* java.util.stream.Stream#filter filter} on the {@code Stream}
* returned by {@code walk} method, this method may be more efficient by
* avoiding redundant retrieval of the {@code BasicFileAttributes}.
*
* <p> If an {@link IOException} is thrown when accessing the directory
* after returned from this method, it is wrapped in an {@link
* UncheckedIOException} which will be thrown from the method that caused
* the access to take place.
*
* @param start
* the starting file
* @param maxDepth
* the maximum number of directory levels to search
* @param matcher
* the function used to decide whether a file should be included
* in the returned stream
* @param options
* options to configure the traversal
*
* @return the {@link CloseableStream} of {@link Path}
*
* @throws IllegalArgumentException
* if the {@code maxDepth} parameter is negative
* @throws SecurityException
* If the security manager denies access to the starting file.
* In the case of the default provider, the {@link
* SecurityManager#checkRead(String) checkRead} method is invoked
* to check read access to the directory.
* @throws IOException
* if an I/O error is thrown when accessing the starting file.
*
* @see #walk(Path, int, FileVisitOption...)
* @since 1.8
*/
public static CloseableStream<Path> find(Path start,
int maxDepth,
BiPredicate<Path, BasicFileAttributes> matcher,
FileVisitOption... options)
throws IOException
{
FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
return new DelegatingCloseableStream<>(iterator,
StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
.filter(entry -> matcher.test(entry.file(), entry.attributes()))
.map(entry -> entry.file()));
}
/**
* Read all lines from a file as a {@code CloseableStream}. Unlike {@link
* #readAllLines(Path, Charset) readAllLines}, this method does not read
* all lines into a {@code List}, but instead populates lazily as the stream
* is consumed.
*
* <p> Bytes from the file are decoded into characters using the specified
* charset and the same line terminators as specified by {@code
* readAllLines} are supported.
*
* <p> After this method returns, then any subsequent I/O exception that
* occurs while reading from the file or when a malformed or unmappable byte
* sequence is read, is wrapped in an {@link UncheckedIOException} that will
* be thrown form the
* {@link java.util.stream.Stream} method that caused the read to take
* place. In case an {@code IOException} is thrown when closing the file,
* it is also wrapped as an {@code UncheckedIOException}.
*
* <p> When not using the try-with-resources construct, then stream's
* {@link CloseableStream#close close} method should be invoked after
* operation is completed so as to free any resources held for the open
* file.
*
* @param path
* the path to the file
* @param cs
* the charset to use for decoding
*
* @return the lines from the file as a {@code CloseableStream}
*
* @throws IOException
* if an I/O error occurs opening the file
* @throws SecurityException
* In the case of the default provider, and a security manager is
* installed, the {@link SecurityManager#checkRead(String) checkRead}
* method is invoked to check read access to the file.
*
* @see #readAllLines(Path, Charset)
* @see #newBufferedReader(Path, Charset)
* @see java.io.BufferedReader#lines()
* @since 1.8
*/
public static CloseableStream<String> lines(Path path, Charset cs)
throws IOException
{
BufferedReader br = Files.newBufferedReader(path, cs);
return new DelegatingCloseableStream<>(br, br.lines());
}
}
......@@ -59,7 +59,7 @@ import sun.util.locale.provider.TimeZoneNameUtility;
* <code>DateFormatSymbols</code> is a public class for encapsulating
* localizable date-time formatting data, such as the names of the
* months, the names of the days of the week, and the time zone data.
* <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
* <code>SimpleDateFormat</code> uses
* <code>DateFormatSymbols</code> to encapsulate this information.
*
* <p>
......
......@@ -86,9 +86,13 @@ class ComparableTimSort {
private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
/**
* Temp storage for merges.
* Temp storage for merges. A workspace array may optionally be
* provided in constructor, and if so will be used as long as it
* is big enough.
*/
private Object[] tmp;
private int tmpBase; // base of tmp array slice
private int tmpLen; // length of tmp array slice
/**
* A stack of pending runs yet to be merged. Run i starts at
......@@ -108,15 +112,27 @@ class ComparableTimSort {
* Creates a TimSort instance to maintain the state of an ongoing sort.
*
* @param a the array to be sorted
* @param work a workspace array (slice)
* @param workBase origin of usable space in work array
* @param workLen usable size of work array
*/
private ComparableTimSort(Object[] a) {
private ComparableTimSort(Object[] a, Object[] work, int workBase, int workLen) {
this.a = a;
// Allocate temp storage (which may be increased later if necessary)
int len = a.length;
Object[] newArray = new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
tmp = newArray;
int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
if (work == null || workLen < tlen || workBase + tlen > work.length) {
tmp = new Object[tlen];
tmpBase = 0;
tmpLen = tlen;
}
else {
tmp = work;
tmpBase = workBase;
tmpLen = workLen;
}
/*
* Allocate runs-to-be-merged stack (which cannot be expanded). The
......@@ -136,17 +152,28 @@ class ComparableTimSort {
}
/*
* The next two methods (which are package private and static) constitute
* the entire API of this class. Each of these methods obeys the contract
* of the public method with the same signature in java.util.Arrays.
* The next method (package private and static) constitutes the
* entire API of this class.
*/
static void sort(Object[] a) {
sort(a, 0, a.length);
}
/**
* Sorts the given range, using the given workspace array slice
* for temp storage when possible. This method is designed to be
* invoked from public methods (in class Arrays) after performing
* any necessary array bounds checks and expanding parameters into
* the required forms.
*
* @param a the array to be sorted
* @param lo the index of the first element, inclusive, to be sorted
* @param hi the index of the last element, exclusive, to be sorted
* @param work a workspace array (slice)
* @param workBase origin of usable space in work array
* @param workLen usable size of work array
* @since 1.8
*/
static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) {
assert a != null && lo >= 0 && lo <= hi && hi <= a.length;
static void sort(Object[] a, int lo, int hi) {
rangeCheck(a.length, lo, hi);
int nRemaining = hi - lo;
if (nRemaining < 2)
return; // Arrays of size 0 and 1 are always sorted
......@@ -163,7 +190,7 @@ class ComparableTimSort {
* extending short natural runs to minRun elements, and merging runs
* to maintain stack invariant.
*/
ComparableTimSort ts = new ComparableTimSort(a);
ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
int minRun = minRunLength(nRemaining);
do {
// Identify next run
......@@ -619,11 +646,11 @@ class ComparableTimSort {
// Copy first run into temp array
Object[] a = this.a; // For performance
Object[] tmp = ensureCapacity(len1);
System.arraycopy(a, base1, tmp, 0, len1);
int cursor1 = 0; // Indexes into tmp array
int cursor1 = tmpBase; // Indexes into tmp array
int cursor2 = base2; // Indexes int a
int dest = base1; // Indexes int a
System.arraycopy(a, base1, tmp, cursor1, len1);
// Move first element of second run and deal with degenerate cases
a[dest++] = a[cursor2++];
......@@ -736,16 +763,17 @@ class ComparableTimSort {
// Copy second run into temp array
Object[] a = this.a; // For performance
Object[] tmp = ensureCapacity(len2);
System.arraycopy(a, base2, tmp, 0, len2);
int tmpBase = this.tmpBase;
System.arraycopy(a, base2, tmp, tmpBase, len2);
int cursor1 = base1 + len1 - 1; // Indexes into a
int cursor2 = len2 - 1; // Indexes into tmp array
int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
int dest = base2 + len2 - 1; // Indexes into a
// Move last element of first run and deal with degenerate cases
a[dest--] = a[cursor1--];
if (--len1 == 0) {
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
return;
}
if (len2 == 1) {
......@@ -803,7 +831,7 @@ class ComparableTimSort {
if (--len2 == 1)
break outer;
count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, 0, len2, len2 - 1);
count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, tmpBase, len2, len2 - 1);
if (count2 != 0) {
dest -= count2;
cursor2 -= count2;
......@@ -835,7 +863,7 @@ class ComparableTimSort {
} else {
assert len1 == 0;
assert len2 > 0;
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
}
}
......@@ -848,7 +876,7 @@ class ComparableTimSort {
* @return tmp, whether or not it grew
*/
private Object[] ensureCapacity(int minCapacity) {
if (tmp.length < minCapacity) {
if (tmpLen < minCapacity) {
// Compute smallest power of 2 > minCapacity
int newSize = minCapacity;
newSize |= newSize >> 1;
......@@ -863,30 +891,13 @@ class ComparableTimSort {
else
newSize = Math.min(newSize, a.length >>> 1);
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
Object[] newArray = new Object[newSize];
tmp = newArray;
tmpLen = newSize;
tmpBase = 0;
}
return tmp;
}
/**
* Checks that fromIndex and toIndex are in range, and throws an
* appropriate exception if they aren't.
*
* @param arrayLen the length of the array
* @param fromIndex the index of the first element of the range
* @param toIndex the index after the last element of the range
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0
* or toIndex > arrayLen
*/
private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex+")");
if (fromIndex < 0)
throw new ArrayIndexOutOfBoundsException(fromIndex);
if (toIndex > arrayLen)
throw new ArrayIndexOutOfBoundsException(toIndex);
}
}
......@@ -89,7 +89,7 @@ import sun.util.ResourceBundleEnumeration;
*
* public class MyResources_fr extends ListResourceBundle {
* protected Object[][] getContents() {
* return new Object[][] = {
* return new Object[][] {
* // LOCALIZE THIS
* {"s1", "Le disque \"{1}\" {0}."}, // MessageFormat pattern
* {"s2", "1"}, // location of {0} in pattern
......
......@@ -124,6 +124,8 @@ public class PropertyResourceBundle extends ResourceBundle {
* to read from.
* @throws IOException if an I/O error occurs
* @throws NullPointerException if <code>stream</code> is null
* @throws IllegalArgumentException if {@code stream} contains a
* malformed Unicode escape sequence.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public PropertyResourceBundle (InputStream stream) throws IOException {
......@@ -142,6 +144,8 @@ public class PropertyResourceBundle extends ResourceBundle {
* read from.
* @throws IOException if an I/O error occurs
* @throws NullPointerException if <code>reader</code> is null
* @throws IllegalArgumentException if a malformed Unicode escape sequence appears
* from {@code reader}.
* @since 1.6
*/
@SuppressWarnings({"unchecked", "rawtypes"})
......
......@@ -140,32 +140,32 @@ import java.util.function.LongConsumer;
* (in approximate order of decreasing desirability):
* <ul>
* <li>The source cannot be structurally interfered with.
* </br>For example, an instance of
* <br>For example, an instance of
* {@link java.util.concurrent.CopyOnWriteArrayList} is an immutable source.
* A Spliterator created from the source reports a characteristic of
* {@code IMMUTABLE}.</li>
* <li>The source manages concurrent modifications.
* </br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
* <br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
* is a concurrent source. A Spliterator created from the source reports a
* characteristic of {@code CONCURRENT}.</li>
* <li>The mutable source provides a late-binding and fail-fast Spliterator.
* </br>Late binding narrows the window during which interference can affect
* <br>Late binding narrows the window during which interference can affect
* the calculation; fail-fast detects, on a best-effort basis, that structural
* interference has occurred after traversal has commenced and throws
* {@link ConcurrentModificationException}. For example, {@link ArrayList},
* and many other non-concurrent {@code Collection} classes in the JDK, provide
* a late-binding, fail-fast spliterator.</li>
* <li>The mutable source provides a non-late-binding but fail-fast Spliterator.
* </br>The source increases the likelihood of throwing
* <br>The source increases the likelihood of throwing
* {@code ConcurrentModificationException} since the window of potential
* interference is larger.</li>
* <li>The mutable source provides a late-binding and non-fail-fast Spliterator.
* </br>The source risks arbitrary, non-deterministic behavior after traversal
* <br>The source risks arbitrary, non-deterministic behavior after traversal
* has commenced since interference is not detected.
* </li>
* <li>The mutable source provides a non-late-binding and non-fail-fast
* Spliterator.
* </br>The source increases the risk of arbitrary, non-deterministic behavior
* <br>The source increases the risk of arbitrary, non-deterministic behavior
* since non-detected interference may occur after construction.
* </li>
* </ul>
......@@ -284,6 +284,8 @@ import java.util.function.LongConsumer;
* is set to {@code true} then diagnostic warnings are reported if boxing of
* primitive values occur when operating on primitive subtype specializations.
*
* @param <T> the type of elements returned by this Spliterator
*
* @see Collection
* @since 1.8
*/
......@@ -333,9 +335,8 @@ public interface Spliterator<T> {
* Upon non-null return:
* <ul>
* <li>the value reported for {@code estimateSize()} before splitting,
* if not already zero or {@code Long.MAX_VALUE}, must, after splitting, be
* greater than {@code estimateSize()} for this and the returned
* Spliterator; and</li>
* must, after splitting, be greater than or equal to {@code estimateSize()}
* for this and the returned Spliterator; and</li>
* <li>if this Spliterator is {@code SUBSIZED}, then {@code estimateSize()}
* for this spliterator before splitting must be equal to the sum of
* {@code estimateSize()} for this and the returned Spliterator after
......@@ -566,13 +567,28 @@ public interface Spliterator<T> {
public static final int SUBSIZED = 0x00004000;
/**
* A Spliterator specialized for {@code int} values.
* A Spliterator specialized for primitive values.
*
* @param <T> the type of elements returned by this Spliterator. The
* type must be a wrapper type for a primitive type, such as {@code Integer}
* for the primitive {@code int} type.
* @param <T_CONS> the type of primitive consumer. The type must be a
* primitive specialization of {@link java.util.function.Consumer} for
* {@code T}, such as {@link java.util.function.IntConsumer} for
* {@code Integer}.
* @param <T_SPLITR> the type of primitive Spliterator. The type must be
* a primitive specialization of Spliterator for {@code T}, such as
* {@link Spliterator.OfInt} for {@code Integer}.
*
* @see Spliterator.OfInt
* @see Spliterator.OfLong
* @see Spliterator.OfDouble
* @since 1.8
*/
public interface OfInt extends Spliterator<Integer> {
public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
extends Spliterator<T> {
@Override
OfInt trySplit();
T_SPLITR trySplit();
/**
* If a remaining element exists, performs the given action on it,
......@@ -586,7 +602,7 @@ public interface Spliterator<T> {
* upon entry to this method, else {@code true}.
* @throws NullPointerException if the specified action is null
*/
boolean tryAdvance(IntConsumer action);
boolean tryAdvance(T_CONS action);
/**
* Performs the given action for each remaining element, sequentially in
......@@ -603,6 +619,24 @@ public interface Spliterator<T> {
* @param action The action
* @throws NullPointerException if the specified action is null
*/
default void forEachRemaining(T_CONS action) {
do { } while (tryAdvance(action));
}
}
/**
* A Spliterator specialized for {@code int} values.
* @since 1.8
*/
public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {
@Override
OfInt trySplit();
@Override
boolean tryAdvance(IntConsumer action);
@Override
default void forEachRemaining(IntConsumer action) {
do { } while (tryAdvance(action));
}
......@@ -658,40 +692,15 @@ public interface Spliterator<T> {
* A Spliterator specialized for {@code long} values.
* @since 1.8
*/
public interface OfLong extends Spliterator<Long> {
public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {
@Override
OfLong trySplit();
/**
* If a remaining element exists, performs the given action on it,
* returning {@code true}; else returns {@code false}. If this
* Spliterator is {@link #ORDERED} the action is performed on the
* next element in encounter order. Exceptions thrown by the
* action are relayed to the caller.
*
* @param action The action
* @return {@code false} if no remaining elements existed
* upon entry to this method, else {@code true}.
* @throws NullPointerException if the specified action is null
*/
@Override
boolean tryAdvance(LongConsumer action);
/**
* Performs the given action for each remaining element, sequentially in
* the current thread, until all elements have been processed or the
* action throws an exception. If this Spliterator is {@link #ORDERED},
* actions are performed in encounter order. Exceptions thrown by the
* action are relayed to the caller.
*
* @implSpec
* The default implementation repeatedly invokes {@link #tryAdvance}
* until it returns {@code false}. It should be overridden whenever
* possible.
*
* @param action The action
* @throws NullPointerException if the specified action is null
*/
@Override
default void forEachRemaining(LongConsumer action) {
do { } while (tryAdvance(action));
}
......@@ -747,40 +756,15 @@ public interface Spliterator<T> {
* A Spliterator specialized for {@code double} values.
* @since 1.8
*/
public interface OfDouble extends Spliterator<Double> {
public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {
@Override
OfDouble trySplit();
/**
* If a remaining element exists, performs the given action on it,
* returning {@code true}; else returns {@code false}. If this
* Spliterator is {@link #ORDERED} the action is performed on the
* next element in encounter order. Exceptions thrown by the
* action are relayed to the caller.
*
* @param action The action
* @return {@code false} if no remaining elements existed
* upon entry to this method, else {@code true}.
* @throws NullPointerException if the specified action is null
*/
@Override
boolean tryAdvance(DoubleConsumer action);
/**
* Performs the given action for each remaining element, sequentially in
* the current thread, until all elements have been processed or the
* action throws an exception. If this Spliterator is {@link #ORDERED},
* actions are performed in encounter order. Exceptions thrown by the
* action are relayed to the caller.
*
* @implSpec
* The default implementation repeatedly invokes {@link #tryAdvance}
* until it returns {@code false}. It should be overridden whenever
* possible.
*
* @param action The action
* @throws NullPointerException if the specified action is null
*/
@Override
default void forEachRemaining(DoubleConsumer action) {
do { } while (tryAdvance(action));
}
......
......@@ -111,9 +111,13 @@ class TimSort<T> {
private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
/**
* Temp storage for merges.
* Temp storage for merges. A workspace array may optionally be
* provided in constructor, and if so will be used as long as it
* is big enough.
*/
private T[] tmp; // Actual runtime type will be Object[], regardless of T
private T[] tmp;
private int tmpBase; // base of tmp array slice
private int tmpLen; // length of tmp array slice
/**
* A stack of pending runs yet to be merged. Run i starts at
......@@ -134,17 +138,31 @@ class TimSort<T> {
*
* @param a the array to be sorted
* @param c the comparator to determine the order of the sort
* @param work a workspace array (slice)
* @param workBase origin of usable space in work array
* @param workLen usable size of work array
*/
private TimSort(T[] a, Comparator<? super T> c) {
private TimSort(T[] a, Comparator<? super T> c, T[] work, int workBase, int workLen) {
this.a = a;
this.c = c;
// Allocate temp storage (which may be increased later if necessary)
int len = a.length;
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
T[] newArray = (T[]) new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
tmp = newArray;
int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
if (work == null || workLen < tlen || workBase + tlen > work.length) {
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
T[] newArray = (T[])java.lang.reflect.Array.newInstance
(a.getClass().getComponentType(), tlen);
tmp = newArray;
tmpBase = 0;
tmpLen = tlen;
}
else {
tmp = work;
tmpBase = workBase;
tmpLen = workLen;
}
/*
* Allocate runs-to-be-merged stack (which cannot be expanded). The
......@@ -164,22 +182,30 @@ class TimSort<T> {
}
/*
* The next two methods (which are package private and static) constitute
* the entire API of this class. Each of these methods obeys the contract
* of the public method with the same signature in java.util.Arrays.
* The next method (package private and static) constitutes the
* entire API of this class.
*/
static <T> void sort(T[] a, Comparator<? super T> c) {
sort(a, 0, a.length, c);
}
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c) {
if (c == null) {
Arrays.sort(a, lo, hi);
return;
}
/**
* Sorts the given range, using the given workspace array slice
* for temp storage when possible. This method is designed to be
* invoked from public methods (in class Arrays) after performing
* any necessary array bounds checks and expanding parameters into
* the required forms.
*
* @param a the array to be sorted
* @param lo the index of the first element, inclusive, to be sorted
* @param hi the index of the last element, exclusive, to be sorted
* @param c the comparator to use
* @param work a workspace array (slice)
* @param workBase origin of usable space in work array
* @param workLen usable size of work array
* @since 1.8
*/
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
T[] work, int workBase, int workLen) {
assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
rangeCheck(a.length, lo, hi);
int nRemaining = hi - lo;
if (nRemaining < 2)
return; // Arrays of size 0 and 1 are always sorted
......@@ -196,7 +222,7 @@ class TimSort<T> {
* extending short natural runs to minRun elements, and merging runs
* to maintain stack invariant.
*/
TimSort<T> ts = new TimSort<>(a, c);
TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
int minRun = minRunLength(nRemaining);
do {
// Identify next run
......@@ -653,11 +679,10 @@ class TimSort<T> {
// Copy first run into temp array
T[] a = this.a; // For performance
T[] tmp = ensureCapacity(len1);
System.arraycopy(a, base1, tmp, 0, len1);
int cursor1 = 0; // Indexes into tmp array
int cursor1 = tmpBase; // Indexes into tmp array
int cursor2 = base2; // Indexes int a
int dest = base1; // Indexes int a
System.arraycopy(a, base1, tmp, cursor1, len1);
// Move first element of second run and deal with degenerate cases
a[dest++] = a[cursor2++];
......@@ -770,16 +795,17 @@ class TimSort<T> {
// Copy second run into temp array
T[] a = this.a; // For performance
T[] tmp = ensureCapacity(len2);
System.arraycopy(a, base2, tmp, 0, len2);
int tmpBase = this.tmpBase;
System.arraycopy(a, base2, tmp, tmpBase, len2);
int cursor1 = base1 + len1 - 1; // Indexes into a
int cursor2 = len2 - 1; // Indexes into tmp array
int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
int dest = base2 + len2 - 1; // Indexes into a
// Move last element of first run and deal with degenerate cases
a[dest--] = a[cursor1--];
if (--len1 == 0) {
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
return;
}
if (len2 == 1) {
......@@ -838,7 +864,7 @@ class TimSort<T> {
if (--len2 == 1)
break outer;
count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c);
count2 = len2 - gallopLeft(a[cursor1], tmp, tmpBase, len2, len2 - 1, c);
if (count2 != 0) {
dest -= count2;
cursor2 -= count2;
......@@ -870,7 +896,7 @@ class TimSort<T> {
} else {
assert len1 == 0;
assert len2 > 0;
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
}
}
......@@ -883,7 +909,7 @@ class TimSort<T> {
* @return tmp, whether or not it grew
*/
private T[] ensureCapacity(int minCapacity) {
if (tmp.length < minCapacity) {
if (tmpLen < minCapacity) {
// Compute smallest power of 2 > minCapacity
int newSize = minCapacity;
newSize |= newSize >> 1;
......@@ -899,30 +925,12 @@ class TimSort<T> {
newSize = Math.min(newSize, a.length >>> 1);
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
T[] newArray = (T[]) new Object[newSize];
T[] newArray = (T[])java.lang.reflect.Array.newInstance
(a.getClass().getComponentType(), newSize);
tmp = newArray;
tmpLen = newSize;
tmpBase = 0;
}
return tmp;
}
/**
* Checks that fromIndex and toIndex are in range, and throws an
* appropriate exception if they aren't.
*
* @param arrayLen the length of the array
* @param fromIndex the index of the first element of the range
* @param toIndex the index after the last element of the range
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0
* or toIndex > arrayLen
*/
private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex+")");
if (fromIndex < 0)
throw new ArrayIndexOutOfBoundsException(fromIndex);
if (toIndex > arrayLen)
throw new ArrayIndexOutOfBoundsException(toIndex);
}
}
......@@ -44,19 +44,19 @@ import java.io.Serializable;
* adjustable expected concurrency for updates. This class obeys the
* same functional specification as {@link java.util.Hashtable}, and
* includes versions of methods corresponding to each method of
* <tt>Hashtable</tt>. However, even though all operations are
* {@code Hashtable}. However, even though all operations are
* thread-safe, retrieval operations do <em>not</em> entail locking,
* and there is <em>not</em> any support for locking the entire table
* in a way that prevents all access. This class is fully
* interoperable with <tt>Hashtable</tt> in programs that rely on its
* interoperable with {@code Hashtable} in programs that rely on its
* thread safety but not on its synchronization details.
*
* <p> Retrieval operations (including <tt>get</tt>) generally do not
* <p> Retrieval operations (including {@code get}) generally do not
* block, so may overlap with update operations (including
* <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
* {@code put} and {@code remove}). Retrievals reflect the results
* of the most recently <em>completed</em> update operations holding
* upon their onset. For aggregate operations such as <tt>putAll</tt>
* and <tt>clear</tt>, concurrent retrievals may reflect insertion or
* upon their onset. For aggregate operations such as {@code putAll}
* and {@code clear}, concurrent retrievals may reflect insertion or
* removal of only some entries. Similarly, Iterators and
* Enumerations return elements reflecting the state of the hash table
* at some point at or since the creation of the iterator/enumeration.
......@@ -64,8 +64,8 @@ import java.io.Serializable;
* However, iterators are designed to be used by only one thread at a time.
*
* <p> The allowed concurrency among update operations is guided by
* the optional <tt>concurrencyLevel</tt> constructor argument
* (default <tt>16</tt>), which is used as a hint for internal sizing. The
* the optional {@code concurrencyLevel} constructor argument
* (default {@code 16}), which is used as a hint for internal sizing. The
* table is internally partitioned to try to permit the indicated
* number of concurrent updates without contention. Because placement
* in hash tables is essentially random, the actual concurrency will
......@@ -85,8 +85,8 @@ import java.io.Serializable;
* <em>optional</em> methods of the {@link Map} and {@link Iterator}
* interfaces.
*
* <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
* does <em>not</em> allow <tt>null</tt> to be used as a key or value.
* <p>Like {@link Hashtable} but unlike {@link HashMap}, this class
* does <em>not</em> allow {@code null} to be used as a key or value.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
......@@ -353,8 +353,8 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
/**
* The table is rehashed when its size exceeds this threshold.
* (The value of this field is always <tt>(int)(capacity *
* loadFactor)</tt>.)
* (The value of this field is always {@code (int)(capacity *
* loadFactor)}.)
*/
transient int threshold;
......@@ -829,9 +829,9 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
}
/**
* Returns <tt>true</tt> if this map contains no key-value mappings.
* Returns {@code true} if this map contains no key-value mappings.
*
* @return <tt>true</tt> if this map contains no key-value mappings
* @return {@code true} if this map contains no key-value mappings
*/
public boolean isEmpty() {
/*
......@@ -870,8 +870,8 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
/**
* Returns the number of key-value mappings in this map. If the
* map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
* map contains more than {@code Integer.MAX_VALUE} elements, returns
* {@code Integer.MAX_VALUE}.
*
* @return the number of key-value mappings in this map
*/
......@@ -948,10 +948,10 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
/**
* Tests if the specified object is a key in this table.
*
* @param key possible key
* @return <tt>true</tt> if and only if the specified object
* @param key possible key
* @return {@code true} if and only if the specified object
* is a key in this table, as determined by the
* <tt>equals</tt> method; <tt>false</tt> otherwise.
* {@code equals} method; {@code false} otherwise
* @throws NullPointerException if the specified key is null
*/
@SuppressWarnings("unchecked")
......@@ -974,13 +974,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
}
/**
* Returns <tt>true</tt> if this map maps one or more keys to the
* specified value. Note: This method requires a full internal
* traversal of the hash table, and so is much slower than
* method <tt>containsKey</tt>.
* Returns {@code true} if this map maps one or more keys to the
* specified value. Note: This method requires a full traversal
* of the map, and so is much slower than method {@code containsKey}.
*
* @param value value whose presence in this map is to be tested
* @return <tt>true</tt> if this map maps one or more keys to the
* @return {@code true} if this map maps one or more keys to the
* specified value
* @throws NullPointerException if the specified value is null
*/
......@@ -1033,16 +1032,16 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
/**
* Legacy method testing if some key maps into the specified value
* in this table. This method is identical in functionality to
* {@link #containsValue}, and exists solely to ensure
* {@link #containsValue(Object)}, and exists solely to ensure
* full compatibility with class {@link java.util.Hashtable},
* which supported this method prior to introduction of the
* Java Collections framework.
*
* @param value a value to search for
* @return <tt>true</tt> if and only if some key maps to the
* <tt>value</tt> argument in this table as
* determined by the <tt>equals</tt> method;
* <tt>false</tt> otherwise
* @return {@code true} if and only if some key maps to the
* {@code value} argument in this table as
* determined by the {@code equals} method;
* {@code false} otherwise
* @throws NullPointerException if the specified value is null
*/
public boolean contains(Object value) {
......@@ -1053,13 +1052,13 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
* Maps the specified key to the specified value in this table.
* Neither the key nor the value can be null.
*
* <p> The value can be retrieved by calling the <tt>get</tt> method
* <p>The value can be retrieved by calling the {@code get} method
* with a key that is equal to the original key.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>
* @return the previous value associated with {@code key}, or
* {@code null} if there was no mapping for {@code key}
* @throws NullPointerException if the specified key or value is null
*/
@SuppressWarnings("unchecked")
......@@ -1079,7 +1078,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
* {@inheritDoc}
*
* @return the previous value associated with the specified key,
* or <tt>null</tt> if there was no mapping for the key
* or {@code null} if there was no mapping for the key
* @throws NullPointerException if the specified key or value is null
*/
@SuppressWarnings("unchecked")
......@@ -1112,8 +1111,8 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
* This method does nothing if the key is not in the map.
*
* @param key the key that needs to be removed
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>
* @return the previous value associated with {@code key}, or
* {@code null} if there was no mapping for {@code key}
* @throws NullPointerException if the specified key is null
*/
public V remove(Object key) {
......@@ -1151,7 +1150,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
* {@inheritDoc}
*
* @return the previous value associated with the specified key,
* or <tt>null</tt> if there was no mapping for the key
* or {@code null} if there was no mapping for the key
* @throws NullPointerException if the specified key or value is null
*/
public V replace(K key, V value) {
......@@ -1177,14 +1176,14 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
/**
* Returns a {@link Set} view of the keys contained in this map.
* The set is backed by the map, so changes to the map are
* reflected in the set, and vice-versa. The set supports element
* reflected in the set, and vice-versa. The set supports element
* removal, which removes the corresponding mapping from this map,
* via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
* <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
* operations. It does not support the <tt>add</tt> or
* <tt>addAll</tt> operations.
* via the {@code Iterator.remove}, {@code Set.remove},
* {@code removeAll}, {@code retainAll}, and {@code clear}
* operations. It does not support the {@code add} or
* {@code addAll} operations.
*
* <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
* <p>The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
......@@ -1200,12 +1199,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
* The collection is backed by the map, so changes to the map are
* reflected in the collection, and vice-versa. The collection
* supports element removal, which removes the corresponding
* mapping from this map, via the <tt>Iterator.remove</tt>,
* <tt>Collection.remove</tt>, <tt>removeAll</tt>,
* <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not
* support the <tt>add</tt> or <tt>addAll</tt> operations.
* mapping from this map, via the {@code Iterator.remove},
* {@code Collection.remove}, {@code removeAll},
* {@code retainAll}, and {@code clear} operations. It does not
* support the {@code add} or {@code addAll} operations.
*
* <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
* <p>The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
......@@ -1221,12 +1220,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
* The set is backed by the map, so changes to the map are
* reflected in the set, and vice-versa. The set supports element
* removal, which removes the corresponding mapping from the map,
* via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
* <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
* operations. It does not support the <tt>add</tt> or
* <tt>addAll</tt> operations.
* via the {@code Iterator.remove}, {@code Set.remove},
* {@code removeAll}, {@code retainAll}, and {@code clear}
* operations. It does not support the {@code add} or
* {@code addAll} operations.
*
* <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
* <p>The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
......@@ -1440,7 +1439,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
/* ---------------- Serialization Support -------------- */
/**
* Saves the state of the <tt>ConcurrentHashMap</tt> instance to a
* Saves the state of the {@code ConcurrentHashMap} instance to a
* stream (i.e., serializes it).
* @param s the stream
* @serialData
......@@ -1477,8 +1476,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
}
/**
* Reconstitutes the <tt>ConcurrentHashMap</tt> instance from a
* stream (i.e., deserializes it).
* Reconstitutes the instance from a stream (that is, deserializes it).
* @param s the stream
*/
@SuppressWarnings("unchecked")
......
......@@ -24,14 +24,16 @@
*/
package java.util.function;
import java.util.Objects;
/**
* An operation which accepts two input arguments and returns no result. This is
* the two-arity specialization of {@link Consumer}. Unlike most other
* functional interfaces, {@code BiConsumer} is expected to operate via
* side-effects.
*
* @param <T> the type of the first argument to the {@code accept} operation.
* @param <U> the type of the second argument to the {@code accept} operation.
* @param <T> the type of the first argument to the {@code accept} operation
* @param <U> the type of the second argument to the {@code accept} operation
*
* @see Consumer
* @since 1.8
......@@ -47,4 +49,28 @@ public interface BiConsumer<T, U> {
* @param u an input object
*/
void accept(T t, U u);
/**
* Returns a {@code BiConsumer} which performs, in sequence, the operation
* represented by this object followed by the operation represented by
* the other {@code BiConsumer}.
*
* <p>Any exceptions thrown by either {@code accept} method are relayed
* to the caller; if performing this operation throws an exception, the
* other operation will not be performed.
*
* @param other a BiConsumer which will be chained after this BiConsumer
* @return a BiConsumer which performs in sequence the {@code accept} method
* of this BiConsumer and the {@code accept} method of the specified
* BiConsumer operation
* @throws NullPointerException if other is null
*/
default BiConsumer<T, U> chain(BiConsumer<? super T, ? super U> other) {
Objects.requireNonNull(other);
return (l, r) -> {
accept(l, r);
other.accept(l, r);
};
}
}
......@@ -24,15 +24,17 @@
*/
package java.util.function;
import java.util.Objects;
/**
* Apply a function to the input arguments, yielding an appropriate result. This
* is the two-arity specialization of {@link Function}. A function may
* variously provide a mapping between types, object instances or keys and
* values or any other form of transformation upon the input.
*
* @param <T> the type of the first argument to the {@code apply} operation.
* @param <U> the type of the second argument to the {@code apply} operation.
* @param <R> the type of results returned by the {@code apply} operation.
* @param <T> the type of the first argument to the {@code apply} operation
* @param <U> the type of the second argument to the {@code apply} operation
* @param <R> the type of results returned by the {@code apply} operation
*
* @see Function
* @since 1.8
......@@ -48,4 +50,22 @@ public interface BiFunction<T, U, R> {
* @return the function result
*/
R apply(T t, U u);
/**
* Returns a new function which applies this function followed by the
* provided function. If either function throws an exception, it is relayed
* to the caller.
*
* @param <V> Type of output objects to the combined function. May be the
* same type as {@code <T>}, {@code <U>} or {@code <R>}
* @param after An additional function to be applied after this function is
* applied
* @return A function which performs this function followed by the provided
* function
* @throws NullPointerException if after is null
*/
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t, U u) -> after.apply(apply(t, u));
}
}
......@@ -30,8 +30,8 @@ import java.util.Objects;
* Determines if the input objects match some criteria. This is the two-arity
* specialization of {@link Predicate}.
*
* @param <T> the type of the first argument to {@code test}.
* @param <U> the type of the second argument to {@code test}.
* @param <T> the type of the first argument to {@code test}
* @param <U> the type of the second argument to {@code test}
*
* @see Predicate
* @since 1.8
......@@ -42,9 +42,9 @@ public interface BiPredicate<T, U> {
/**
* Return {@code true} if the inputs match some criteria.
*
* @param t an input object.
* @param u an input object.
* @return {@code true} if the inputs match some criteria.
* @param t an input object
* @param u an input object
* @return {@code true} if the inputs match some criteria
*/
boolean test(T t, U u);
......@@ -54,11 +54,12 @@ public interface BiPredicate<T, U> {
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
* @param p a predicate which will be logically-ANDed with this predicate.
* @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
* predicates return {@code true}.
* predicates return {@code true}
* @throws NullPointerException if p is null
*/
public default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> p) {
default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> p) {
Objects.requireNonNull(p);
return (T t, U u) -> test(t, u) && p.test(t, u);
}
......@@ -67,9 +68,9 @@ public interface BiPredicate<T, U> {
* Returns a predicate which negates the result of this predicate.
*
* @return a new predicate who's result is always the opposite of this
* predicate.
* predicate
*/
public default BiPredicate<T, U> negate() {
default BiPredicate<T, U> negate() {
return (T t, U u) -> !test(t, u);
}
......@@ -79,25 +80,13 @@ public interface BiPredicate<T, U> {
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
* @param p a predicate which will be logically-ORed with this predicate.
* @param p a predicate which will be logically-ORed with this predicate
* @return a new predicate which returns {@code true} if either predicate
* returns {@code true}.
* returns {@code true}
* @throws NullPointerException if p is null
*/
public default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> p) {
default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> p) {
Objects.requireNonNull(p);
return (T t, U u) -> test(t, u) || p.test(t, u);
}
/**
* Returns a predicate that evaluates to {@code true} if both or neither of
* the component predicates evaluate to {@code true}.
*
* @param p a predicate which will be logically-XORed with this predicate.
* @return a predicate that evaluates to {@code true} if both or neither of
* the component predicates evaluate to {@code true}.
*/
public default BiPredicate<T, U> xor(BiPredicate<? super T, ? super U> p) {
Objects.requireNonNull(p);
return (T t, U u) -> test(t, u) ^ p.test(t, u);
}
}
......@@ -40,5 +40,5 @@ public interface BooleanSupplier {
*
* @return a {@code boolean} value
*/
public boolean getAsBoolean();
boolean getAsBoolean();
}
......@@ -43,5 +43,5 @@ public interface DoubleBinaryOperator {
* @param right the right operand value
* @return the result of the operation
*/
public double applyAsDouble(double left, double right);
double applyAsDouble(double left, double right);
}
......@@ -43,5 +43,5 @@ public interface DoubleFunction<R> {
* @param value the input value
* @return the function result
*/
public R apply(double value);
R apply(double value);
}
......@@ -39,5 +39,5 @@ public interface DoubleSupplier {
*
* @return a {@code double} value
*/
public double getAsDouble();
double getAsDouble();
}
......@@ -44,5 +44,5 @@ public interface IntBinaryOperator {
* @param right the right operand value
* @return the result of the operation
*/
public int applyAsInt(int left, int right);
int applyAsInt(int left, int right);
}
......@@ -43,5 +43,5 @@ public interface IntFunction<R> {
* @param value the input value
* @return the function result
*/
public R apply(int value);
R apply(int value);
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册