Skip to content

Commit

Permalink
DO NOT MERGE
Browse files Browse the repository at this point in the history
Demo of Guava changes for openjdk/jdk#23461.

This change pre-sizes collectors for which the size of the output collection must match the size of the input stream. It omits cases like `ImmutableSet` (which deduplicates), but it includes cases `ImmutableList` (obviously) and `ImmutableMap`/`ImmutableBiMap` (which rejects duplicate keys).

RELNOTES=`collect`: Changed `toImmutableList`, `toImmutableMap`, and `toImmutableBiMap` to internally pre-size their collections when possible.
PiperOrigin-RevId: 725756865
  • Loading branch information
cpovirk authored and Google Java Core Libraries committed Feb 12, 2025
1 parent d650068 commit 37dc5e9
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 6 deletions.
70 changes: 67 additions & 3 deletions android/guava/src/com/google/common/collect/CollectCollectors.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,30 @@
package com.google.common.collect;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Sets.immutableEnumSet;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonMap;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toMap;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Preconditions;
import com.google.common.primitives.Ints;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.TreeMap;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.LongFunction;
import java.util.function.Supplier;
import java.util.function.ToIntFunction;
import java.util.stream.Collector;
import java.util.stream.Collector.Characteristics;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;

Expand All @@ -43,10 +49,60 @@
@SuppressWarnings("Java7ApiChecker")
@IgnoreJRERequirement // used only from APIs with Java 8 types in them
final class CollectCollectors {
private static <
T extends @Nullable Object, A extends @Nullable Object, R extends @Nullable Object>
Collector<T, A, R> sizedCollector(
Supplier<A> supplier,
LongFunction<A> sizedSupplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Function<A, R> finisher,
Characteristics... characteristics) {
ImmutableSet<Characteristics> characteristicsSet = immutableEnumSet(asList(characteristics));
return new Collector<T, A, R>() {
@Override
public Supplier<A> supplier() {
return supplier;
}

// only an override under some future version of Java?
@SuppressWarnings({
"MissingOverride",
"UnusedMethod",
})
public LongFunction<A> sizedSupplier() {
return sizedSupplier;
}

@Override
public BiConsumer<A, T> accumulator() {
return accumulator;
}

@Override
public BinaryOperator<A> combiner() {
return combiner;
}

@Override
public Function<A, R> finisher() {
return finisher;
}

@Override
public ImmutableSet<Characteristics> characteristics() {
return characteristicsSet;
}
};
}

private static final Collector<Object, ?, ImmutableList<Object>> TO_IMMUTABLE_LIST =
Collector.of(
sizedCollector(
ImmutableList::builder,
size ->
size == -1
? ImmutableList.builder()
: ImmutableList.builderWithExpectedSize(Ints.checkedCast(size)),
ImmutableList.Builder::add,
ImmutableList.Builder::combine,
ImmutableList.Builder::build);
Expand Down Expand Up @@ -191,8 +247,12 @@ ImmutableSet<E> toImmutableSet() {
Function<? super T, ? extends V> valueFunction) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
return Collector.of(
return sizedCollector(
ImmutableMap.Builder<K, V>::new,
size ->
size == -1
? new ImmutableMap.Builder<K, V>()
: new ImmutableMap.Builder<K, V>(Ints.checkedCast(size)),
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
ImmutableMap.Builder::combine,
ImmutableMap.Builder::buildOrThrow);
Expand Down Expand Up @@ -249,8 +309,12 @@ ImmutableSet<E> toImmutableSet() {
Function<? super T, ? extends V> valueFunction) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
return Collector.of(
return sizedCollector(
ImmutableBiMap.Builder<K, V>::new,
size ->
size == -1
? new ImmutableBiMap.Builder<K, V>()
: new ImmutableBiMap.Builder<K, V>(Ints.checkedCast(size)),
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
ImmutableBiMap.Builder::combine,
ImmutableBiMap.Builder::buildOrThrow,
Expand Down
70 changes: 67 additions & 3 deletions guava/src/com/google/common/collect/CollectCollectors.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,90 @@
package com.google.common.collect;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Sets.immutableEnumSet;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonMap;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toMap;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Preconditions;
import com.google.common.primitives.Ints;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.TreeMap;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.LongFunction;
import java.util.function.Supplier;
import java.util.function.ToIntFunction;
import java.util.stream.Collector;
import java.util.stream.Collector.Characteristics;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;

/** Collectors utilities for {@code common.collect} internals. */
@GwtCompatible
final class CollectCollectors {
private static <
T extends @Nullable Object, A extends @Nullable Object, R extends @Nullable Object>
Collector<T, A, R> sizedCollector(
Supplier<A> supplier,
LongFunction<A> sizedSupplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Function<A, R> finisher,
Characteristics... characteristics) {
ImmutableSet<Characteristics> characteristicsSet = immutableEnumSet(asList(characteristics));
return new Collector<T, A, R>() {
@Override
public Supplier<A> supplier() {
return supplier;
}

// only an override under some future version of Java?
@SuppressWarnings({
"MissingOverride",
"UnusedMethod",
})
public LongFunction<A> sizedSupplier() {
return sizedSupplier;
}

@Override
public BiConsumer<A, T> accumulator() {
return accumulator;
}

@Override
public BinaryOperator<A> combiner() {
return combiner;
}

@Override
public Function<A, R> finisher() {
return finisher;
}

@Override
public ImmutableSet<Characteristics> characteristics() {
return characteristicsSet;
}
};
}

private static final Collector<Object, ?, ImmutableList<Object>> TO_IMMUTABLE_LIST =
Collector.of(
sizedCollector(
ImmutableList::builder,
size ->
size == -1
? ImmutableList.builder()
: ImmutableList.builderWithExpectedSize(Ints.checkedCast(size)),
ImmutableList.Builder::add,
ImmutableList.Builder::combine,
ImmutableList.Builder::build);
Expand Down Expand Up @@ -188,8 +244,12 @@ ImmutableSet<E> toImmutableSet() {
Function<? super T, ? extends V> valueFunction) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
return Collector.of(
return sizedCollector(
ImmutableMap.Builder<K, V>::new,
size ->
size == -1
? new ImmutableMap.Builder<K, V>()
: new ImmutableMap.Builder<K, V>(Ints.checkedCast(size)),
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
ImmutableMap.Builder::combine,
ImmutableMap.Builder::buildOrThrow);
Expand Down Expand Up @@ -246,8 +306,12 @@ ImmutableSet<E> toImmutableSet() {
Function<? super T, ? extends V> valueFunction) {
checkNotNull(keyFunction);
checkNotNull(valueFunction);
return Collector.of(
return sizedCollector(
ImmutableBiMap.Builder<K, V>::new,
size ->
size == -1
? new ImmutableBiMap.Builder<K, V>()
: new ImmutableBiMap.Builder<K, V>(Ints.checkedCast(size)),
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
ImmutableBiMap.Builder::combine,
ImmutableBiMap.Builder::buildOrThrow,
Expand Down

0 comments on commit 37dc5e9

Please sign in to comment.