8156079: consider making empty instances singletons

8169222: minor immutable collections optimizations

Reviewed-by: forax, redestad, alanb
This commit is contained in:
Stuart Marks 2016-11-04 14:29:34 -07:00
parent 766e807c18
commit d55905fe1b
4 changed files with 36 additions and 14 deletions

View file

@ -53,7 +53,8 @@ class ImmutableCollections {
*/ */
static final int SALT; static final int SALT;
static { static {
SALT = new Random().nextInt(); long nt = System.nanoTime();
SALT = (int)((nt >>> 32) ^ nt);
} }
/** No instances. */ /** No instances. */
@ -63,7 +64,7 @@ class ImmutableCollections {
* The reciprocal of load factor. Given a number of elements * The reciprocal of load factor. Given a number of elements
* to store, multiply by this factor to get the table size. * to store, multiply by this factor to get the table size.
*/ */
static final double EXPAND_FACTOR = 2.0; static final int EXPAND_FACTOR = 2;
static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); } static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); }
@ -84,7 +85,14 @@ class ImmutableCollections {
} }
static final class List0<E> extends AbstractImmutableList<E> { static final class List0<E> extends AbstractImmutableList<E> {
List0() { } private static final List0<?> INSTANCE = new List0<>();
@SuppressWarnings("unchecked")
static <T> List0<T> instance() {
return (List0<T>) INSTANCE;
}
private List0() { }
@Override @Override
public int size() { public int size() {
@ -214,7 +222,14 @@ class ImmutableCollections {
} }
static final class Set0<E> extends AbstractImmutableSet<E> { static final class Set0<E> extends AbstractImmutableSet<E> {
Set0() { } private static final Set0<?> INSTANCE = new Set0<>();
@SuppressWarnings("unchecked")
static <T> Set0<T> instance() {
return (Set0<T>) INSTANCE;
}
private Set0() { }
@Override @Override
public int size() { public int size() {
@ -351,7 +366,7 @@ class ImmutableCollections {
SetN(E... input) { SetN(E... input) {
size = input.length; // implicit nullcheck of input size = input.length; // implicit nullcheck of input
elements = (E[])new Object[(int)Math.ceil(EXPAND_FACTOR * input.length)]; elements = (E[])new Object[EXPAND_FACTOR * input.length];
for (int i = 0; i < input.length; i++) { for (int i = 0; i < input.length; i++) {
E e = Objects.requireNonNull(input[i]); E e = Objects.requireNonNull(input[i]);
int idx = probe(e); int idx = probe(e);
@ -450,7 +465,14 @@ class ImmutableCollections {
} }
static final class Map0<K,V> extends AbstractImmutableMap<K,V> { static final class Map0<K,V> extends AbstractImmutableMap<K,V> {
Map0() { } private static final Map0<?,?> INSTANCE = new Map0<>();
@SuppressWarnings("unchecked")
static <K,V> Map0<K,V> instance() {
return (Map0<K,V>) INSTANCE;
}
private Map0() { }
@Override @Override
public Set<Map.Entry<K,V>> entrySet() { public Set<Map.Entry<K,V>> entrySet() {
@ -529,7 +551,7 @@ class ImmutableCollections {
} }
size = input.length >> 1; size = input.length >> 1;
int len = (int)Math.ceil(EXPAND_FACTOR * input.length); int len = EXPAND_FACTOR * input.length;
len = (len + 1) & ~1; // ensure table is even length len = (len + 1) & ~1; // ensure table is even length
table = new Object[len]; table = new Object[len];
@ -789,7 +811,7 @@ final class CollSer implements Serializable {
return Set.of(array); return Set.of(array);
case IMM_MAP: case IMM_MAP:
if (array.length == 0) { if (array.length == 0) {
return new ImmutableCollections.Map0<>(); return ImmutableCollections.Map0.instance();
} else if (array.length == 2) { } else if (array.length == 2) {
return new ImmutableCollections.Map1<>(array[0], array[1]); return new ImmutableCollections.Map1<>(array[0], array[1]);
} else { } else {

View file

@ -786,7 +786,7 @@ public interface List<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> List<E> of() { static <E> List<E> of() {
return new ImmutableCollections.List0<>(); return ImmutableCollections.List0.instance();
} }
/** /**
@ -1030,7 +1030,7 @@ public interface List<E> extends Collection<E> {
Objects.requireNonNull(elements); Objects.requireNonNull(elements);
switch (elements.length) { switch (elements.length) {
case 0: case 0:
return new ImmutableCollections.List0<>(); return ImmutableCollections.List0.instance();
case 1: case 1:
return new ImmutableCollections.List1<>(elements[0]); return new ImmutableCollections.List1<>(elements[0]);
case 2: case 2:

View file

@ -1286,7 +1286,7 @@ public interface Map<K, V> {
* @since 9 * @since 9
*/ */
static <K, V> Map<K, V> of() { static <K, V> Map<K, V> of() {
return new ImmutableCollections.Map0<>(); return ImmutableCollections.Map0.instance();
} }
/** /**
@ -1604,7 +1604,7 @@ public interface Map<K, V> {
static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) { static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
Objects.requireNonNull(entries); Objects.requireNonNull(entries);
if (entries.length == 0) { if (entries.length == 0) {
return new ImmutableCollections.Map0<>(); return ImmutableCollections.Map0.instance();
} else if (entries.length == 1) { } else if (entries.length == 1) {
return new ImmutableCollections.Map1<>(entries[0].getKey(), return new ImmutableCollections.Map1<>(entries[0].getKey(),
entries[0].getValue()); entries[0].getValue());

View file

@ -448,7 +448,7 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> Set<E> of() { static <E> Set<E> of() {
return new ImmutableCollections.Set0<>(); return ImmutableCollections.Set0.instance();
} }
/** /**
@ -692,7 +692,7 @@ public interface Set<E> extends Collection<E> {
Objects.requireNonNull(elements); Objects.requireNonNull(elements);
switch (elements.length) { switch (elements.length) {
case 0: case 0:
return new ImmutableCollections.Set0<>(); return ImmutableCollections.Set0.instance();
case 1: case 1:
return new ImmutableCollections.Set1<>(elements[0]); return new ImmutableCollections.Set1<>(elements[0]);
case 2: case 2: