mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8156071: List.of: reduce array copying during creation
Reviewed-by: psandoz, redestad
This commit is contained in:
parent
ea27a54bf0
commit
88d75c9ad5
6 changed files with 203 additions and 18 deletions
|
@ -36,6 +36,7 @@ import java.util.function.BiFunction;
|
|||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
import jdk.internal.access.JavaUtilCollectionAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.misc.CDS;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
@ -103,7 +104,7 @@ class ImmutableCollections {
|
|||
CDS.initializeFromArchive(ImmutableCollections.class);
|
||||
if (archivedObjects == null) {
|
||||
EMPTY = new Object();
|
||||
EMPTY_LIST = new ListN<>();
|
||||
EMPTY_LIST = new ListN<>(new Object[0]);
|
||||
EMPTY_SET = new SetN<>();
|
||||
EMPTY_MAP = new MapN<>();
|
||||
archivedObjects = new Object[] { EMPTY, EMPTY_LIST, EMPTY_SET, EMPTY_MAP };
|
||||
|
@ -115,6 +116,16 @@ class ImmutableCollections {
|
|||
}
|
||||
}
|
||||
|
||||
static class Access {
|
||||
static {
|
||||
SharedSecrets.setJavaUtilCollectionAccess(new JavaUtilCollectionAccess() {
|
||||
public <E> List<E> listFromTrustedArray(Object[] array) {
|
||||
return ImmutableCollections.ListN.fromTrustedArray(array);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** No instances. */
|
||||
private ImmutableCollections() { }
|
||||
|
||||
|
@ -521,15 +532,31 @@ class ImmutableCollections {
|
|||
@Stable
|
||||
private final E[] elements;
|
||||
|
||||
private ListN(E[] array) {
|
||||
elements = array;
|
||||
}
|
||||
|
||||
// creates a new internal array, and checks and rejects null elements
|
||||
@SafeVarargs
|
||||
ListN(E... input) {
|
||||
static <E> List<E> fromArray(E... input) {
|
||||
// copy and check manually to avoid TOCTOU
|
||||
@SuppressWarnings("unchecked")
|
||||
E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
tmp[i] = Objects.requireNonNull(input[i]);
|
||||
}
|
||||
elements = tmp;
|
||||
return new ListN<>(tmp);
|
||||
}
|
||||
|
||||
// Avoids creating a new array, but checks and rejects null elements.
|
||||
// Declared with Object... arg so that varargs calls don't accidentally
|
||||
// create an array of a subtype.
|
||||
@SuppressWarnings("unchecked")
|
||||
static <E> List<E> fromTrustedArray(Object... input) {
|
||||
for (Object o : input) {
|
||||
Objects.requireNonNull(o);
|
||||
}
|
||||
return new ListN<>((E[])input);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -842,7 +842,7 @@ public interface List<E> extends Collection<E> {
|
|||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3) {
|
||||
return new ImmutableCollections.ListN<>(e1, e2, e3);
|
||||
return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -861,7 +861,7 @@ public interface List<E> extends Collection<E> {
|
|||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4) {
|
||||
return new ImmutableCollections.ListN<>(e1, e2, e3, e4);
|
||||
return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -881,7 +881,7 @@ public interface List<E> extends Collection<E> {
|
|||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) {
|
||||
return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5);
|
||||
return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -902,8 +902,8 @@ public interface List<E> extends Collection<E> {
|
|||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
|
||||
return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
|
||||
e6);
|
||||
return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5,
|
||||
e6);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -925,8 +925,8 @@ public interface List<E> extends Collection<E> {
|
|||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
|
||||
return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
|
||||
e6, e7);
|
||||
return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5,
|
||||
e6, e7);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -949,8 +949,8 @@ public interface List<E> extends Collection<E> {
|
|||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
|
||||
return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
|
||||
e6, e7, e8);
|
||||
return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5,
|
||||
e6, e7, e8);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -974,8 +974,8 @@ public interface List<E> extends Collection<E> {
|
|||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
|
||||
return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
|
||||
e6, e7, e8, e9);
|
||||
return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5,
|
||||
e6, e7, e8, e9);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1000,8 +1000,8 @@ public interface List<E> extends Collection<E> {
|
|||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
|
||||
return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
|
||||
e6, e7, e8, e9, e10);
|
||||
return ImmutableCollections.ListN.fromTrustedArray(e1, e2, e3, e4, e5,
|
||||
e6, e7, e8, e9, e10);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1042,7 +1042,7 @@ public interface List<E> extends Collection<E> {
|
|||
case 2:
|
||||
return new ImmutableCollections.List12<>(elements[0], elements[1]);
|
||||
default:
|
||||
return new ImmutableCollections.ListN<>(elements);
|
||||
return ImmutableCollections.ListN.fromArray(elements);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@ import java.util.function.ToDoubleFunction;
|
|||
import java.util.function.ToIntFunction;
|
||||
import java.util.function.ToLongFunction;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
|
||||
/**
|
||||
* Implementations of {@link Collector} that implement various useful reduction
|
||||
* operations, such as accumulating elements into collections, summarizing
|
||||
|
@ -296,7 +298,8 @@ public final class Collectors {
|
|||
Collector<T, ?, List<T>> toUnmodifiableList() {
|
||||
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
|
||||
(left, right) -> { left.addAll(right); return left; },
|
||||
list -> (List<T>)List.of(list.toArray()),
|
||||
list -> (List<T>)SharedSecrets.getJavaUtilCollectionAccess()
|
||||
.listFromTrustedArray(list.toArray()),
|
||||
CH_NOID);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue