update to 30.1
This commit is contained in:
parent
bb8e73e79a
commit
bc85508c04
81 changed files with 4978 additions and 1367 deletions
|
@ -24,7 +24,9 @@ ext {
|
|||
}
|
||||
|
||||
apply plugin: 'java-library'
|
||||
apply from: rootProject.file('gradle/init/banner.gradle')
|
||||
apply from: rootProject.file('gradle/ide/idea.gradle')
|
||||
apply from: rootProject.file('gradle/compile/repo.gradle')
|
||||
apply from: rootProject.file('gradle/compile/java.gradle')
|
||||
apply from: rootProject.file('gradle/test/junit5.gradle')
|
||||
apply from: rootProject.file('gradle/publishing/publication.gradle')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
group = org.xbib
|
||||
name = guava
|
||||
version = 29.0
|
||||
version = 30.1
|
||||
|
||||
gradle.wrapper.version = 6.6.1
|
||||
|
|
|
@ -17,9 +17,7 @@ compileTestJava {
|
|||
|
||||
jar {
|
||||
manifest {
|
||||
attributes('Implementation-Title': project.name)
|
||||
attributes('Implementation-Version': project.version)
|
||||
attributes('Implementation-Vendor': 'Jörg Prante')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,8 +28,18 @@ task sourcesJar(type: Jar, dependsOn: classes) {
|
|||
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
classifier 'javadoc'
|
||||
from javadoc.destinationDir
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives sourcesJar, javadocJar
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding('UTF-8')
|
||||
options.compilerArgs << '-Xlint:all'
|
||||
}
|
||||
|
||||
javadoc {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
|
|
4
gradle/compile/repo.gradle
Normal file
4
gradle/compile/repo.gradle
Normal file
|
@ -0,0 +1,4 @@
|
|||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
}
|
|
@ -7,7 +7,6 @@ idea {
|
|||
}
|
||||
}
|
||||
|
||||
// if project was not imported via idea pluginw
|
||||
clean {
|
||||
delete 'out'
|
||||
}
|
||||
|
|
14
gradle/init/banner.gradle
Normal file
14
gradle/init/banner.gradle
Normal file
|
@ -0,0 +1,14 @@
|
|||
gradle.projectsLoaded { g ->
|
||||
printf "Host: %s\nOS: %s %s %s\nJVM: %s %s %s %s\nGradle: %s Groovy: %s Java: %s\n" +
|
||||
"Build: group: %s name: %s version: %s\n",
|
||||
InetAddress.getLocalHost(),
|
||||
System.getProperty("os.name"),
|
||||
System.getProperty("os.arch"),
|
||||
System.getProperty("os.version"),
|
||||
System.getProperty("java.version"),
|
||||
System.getProperty("java.vm.version"),
|
||||
System.getProperty("java.vm.vendor"),
|
||||
System.getProperty("java.vm.name"),
|
||||
gradle.gradleVersion, GroovySystem.getVersion(), JavaVersion.current(),
|
||||
gradle.rootProject.group, gradle.rootProject.name, gradle.rootProject.version
|
||||
}
|
|
@ -53,12 +53,14 @@ if (project.hasProperty("signing.keyId")) {
|
|||
}
|
||||
}
|
||||
|
||||
nexusPublishing {
|
||||
repositories {
|
||||
sonatype {
|
||||
username = project.property('ossrhUsername')
|
||||
password = project.property('ossrhPassword')
|
||||
packageGroup = "org.xbib"
|
||||
if (project.hasProperty("ossrhUsername")) {
|
||||
nexusPublishing {
|
||||
repositories {
|
||||
sonatype {
|
||||
username = project.property('ossrhUsername')
|
||||
password = project.property('ossrhPassword')
|
||||
packageGroup = "org.xbib"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
2
gradlew
vendored
2
gradlew
vendored
|
@ -130,7 +130,7 @@ fi
|
|||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
|
|
21
gradlew.bat
vendored
21
gradlew.bat
vendored
|
@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
@ -54,7 +54,7 @@ goto fail
|
|||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
|
@ -64,21 +64,6 @@ echo location of your Java installation.
|
|||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
|
@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
|
|
@ -79,7 +79,15 @@ public enum StandardSystemProperty {
|
|||
/** Name of JIT compiler to use. */
|
||||
JAVA_COMPILER("java.compiler"),
|
||||
|
||||
/** Path of extension directory or directories. */
|
||||
/**
|
||||
* Path of extension directory or directories.
|
||||
*
|
||||
* @deprecated This property was <a
|
||||
* href="https://openjdk.java.net/jeps/220#Removed:-The-extension-mechanism">deprecated</a> in
|
||||
* Java 8 and removed in Java 9. We do not plan to remove this API from Guava, but if you are
|
||||
* using it, it is probably not doing what you want.
|
||||
*/
|
||||
@Deprecated
|
||||
JAVA_EXT_DIRS("java.ext.dirs"),
|
||||
|
||||
/** Operating system name. */
|
||||
|
|
|
@ -480,8 +480,8 @@ public final class CacheBuilder<K, V> {
|
|||
this.maximumWeight);
|
||||
checkState(
|
||||
this.maximumSize == UNSET_INT, "maximum size was already set to %s", this.maximumSize);
|
||||
this.maximumWeight = maximumWeight;
|
||||
checkArgument(maximumWeight >= 0, "maximum weight must not be negative");
|
||||
this.maximumWeight = maximumWeight;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ import com.google.common.cache.CacheBuilder.NullListener;
|
|||
import com.google.common.cache.CacheBuilder.OneWeigher;
|
||||
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
|
||||
import com.google.common.cache.CacheLoader.UnsupportedLoadingOperationException;
|
||||
import com.google.common.cache.LocalCache.AbstractCacheSet;
|
||||
import com.google.common.collect.AbstractSequentialIterator;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -4284,7 +4283,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
|
|||
public Set<K> keySet() {
|
||||
// does not impact recency ordering
|
||||
Set<K> ks = keySet;
|
||||
return (ks != null) ? ks : (keySet = new KeySet(this));
|
||||
return (ks != null) ? ks : (keySet = new KeySet());
|
||||
}
|
||||
|
||||
Collection<V> values;
|
||||
|
@ -4293,7 +4292,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
|
|||
public Collection<V> values() {
|
||||
// does not impact recency ordering
|
||||
Collection<V> vs = values;
|
||||
return (vs != null) ? vs : (values = new Values(this));
|
||||
return (vs != null) ? vs : (values = new Values());
|
||||
}
|
||||
|
||||
Set<Entry<K, V>> entrySet;
|
||||
|
@ -4303,7 +4302,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
|
|||
public Set<Entry<K, V>> entrySet() {
|
||||
// does not impact recency ordering
|
||||
Set<Entry<K, V>> es = entrySet;
|
||||
return (es != null) ? es : (entrySet = new EntrySet(this));
|
||||
return (es != null) ? es : (entrySet = new EntrySet());
|
||||
}
|
||||
|
||||
// Iterator Support
|
||||
|
@ -4494,25 +4493,20 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
|
|||
}
|
||||
|
||||
abstract class AbstractCacheSet<T> extends AbstractSet<T> {
|
||||
final ConcurrentMap<?, ?> map;
|
||||
|
||||
AbstractCacheSet(ConcurrentMap<?, ?> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
return LocalCache.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
return LocalCache.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
map.clear();
|
||||
LocalCache.this.clear();
|
||||
}
|
||||
|
||||
// super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android.
|
||||
|
@ -4556,10 +4550,6 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
|
|||
|
||||
final class KeySet extends AbstractCacheSet<K> {
|
||||
|
||||
KeySet(ConcurrentMap<?, ?> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<K> iterator() {
|
||||
return new KeyIterator();
|
||||
|
@ -4567,36 +4557,31 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
|
|||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return map.containsKey(o);
|
||||
return LocalCache.this.containsKey(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return map.remove(o) != null;
|
||||
return LocalCache.this.remove(o) != null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final class Values extends AbstractCollection<V> {
|
||||
private final ConcurrentMap<?, ?> map;
|
||||
|
||||
Values(ConcurrentMap<?, ?> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
return LocalCache.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
return LocalCache.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
map.clear();
|
||||
LocalCache.this.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4612,7 +4597,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
|
|||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return map.containsValue(o);
|
||||
return LocalCache.this.containsValue(o);
|
||||
}
|
||||
|
||||
// super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android.
|
||||
|
@ -4632,10 +4617,6 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
|
|||
|
||||
final class EntrySet extends AbstractCacheSet<Entry<K, V>> {
|
||||
|
||||
EntrySet(ConcurrentMap<?, ?> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Entry<K, V>> iterator() {
|
||||
return new EntryIterator();
|
||||
|
|
|
@ -88,6 +88,28 @@ final class CartesianList<E> extends AbstractList<List<E>> implements RandomAcce
|
|||
return computedIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
if (!(o instanceof List)) {
|
||||
return -1;
|
||||
}
|
||||
List<?> list = (List<?>) o;
|
||||
if (list.size() != axes.size()) {
|
||||
return -1;
|
||||
}
|
||||
ListIterator<?> itr = list.listIterator();
|
||||
int computedIndex = 0;
|
||||
while (itr.hasNext()) {
|
||||
int axisIndex = itr.nextIndex();
|
||||
int elemIndex = axes.get(axisIndex).lastIndexOf(itr.next());
|
||||
if (elemIndex == -1) {
|
||||
return -1;
|
||||
}
|
||||
computedIndex += elemIndex * axesSizeProduct[axisIndex + 1];
|
||||
}
|
||||
return computedIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<E> get(final int index) {
|
||||
checkElementIndex(index, size());
|
||||
|
@ -117,8 +139,21 @@ final class CartesianList<E> extends AbstractList<List<E>> implements RandomAcce
|
|||
return axesSizeProduct[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return indexOf(o) != -1;
|
||||
public boolean contains(Object object) {
|
||||
if (!(object instanceof List)) {
|
||||
return false;
|
||||
}
|
||||
List<?> list = (List<?>) object;
|
||||
if (list.size() != axes.size()) {
|
||||
return false;
|
||||
}
|
||||
int i = 0;
|
||||
for (Object o : list) {
|
||||
if (!axes.get(i).contains(o)) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,58 +20,291 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.annotations.GwtIncompatible;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Supplier;
|
||||
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.BinaryOperator;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.ToIntFunction;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/** Collectors utilities for {@code common.collect} internals. */
|
||||
@GwtCompatible
|
||||
final class CollectCollectors {
|
||||
static <T, K, V> Collector<T, ?, ImmutableBiMap<K, V>> toImmutableBiMap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
return Collector.of(
|
||||
ImmutableBiMap.Builder<K, V>::new,
|
||||
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
|
||||
ImmutableBiMap.Builder::combine,
|
||||
ImmutableBiMap.Builder::build,
|
||||
new Collector.Characteristics[0]);
|
||||
}
|
||||
|
||||
private static final Collector<Object, ?, ImmutableList<Object>> TO_IMMUTABLE_LIST =
|
||||
Collector.of(
|
||||
ImmutableList::<Object>builder,
|
||||
ImmutableList::builder,
|
||||
ImmutableList.Builder::add,
|
||||
ImmutableList.Builder::combine,
|
||||
ImmutableList.Builder::build);
|
||||
|
||||
private static final Collector<Object, ?, ImmutableSet<Object>> TO_IMMUTABLE_SET =
|
||||
Collector.of(
|
||||
ImmutableSet::builder,
|
||||
ImmutableSet.Builder::add,
|
||||
ImmutableSet.Builder::combine,
|
||||
ImmutableSet.Builder::build);
|
||||
|
||||
@GwtIncompatible
|
||||
private static final Collector<Range<Comparable<?>>, ?, ImmutableRangeSet<Comparable<?>>>
|
||||
TO_IMMUTABLE_RANGE_SET =
|
||||
Collector.of(
|
||||
ImmutableRangeSet::builder,
|
||||
ImmutableRangeSet.Builder::add,
|
||||
ImmutableRangeSet.Builder::combine,
|
||||
ImmutableRangeSet.Builder::build);
|
||||
|
||||
// Lists
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
static <E> Collector<E, ?, ImmutableList<E>> toImmutableList() {
|
||||
return (Collector) TO_IMMUTABLE_LIST;
|
||||
}
|
||||
|
||||
// Sets
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
static <E> Collector<E, ?, ImmutableSet<E>> toImmutableSet() {
|
||||
return (Collector) TO_IMMUTABLE_SET;
|
||||
}
|
||||
|
||||
static <E> Collector<E, ?, ImmutableSortedSet<E>> toImmutableSortedSet(
|
||||
Comparator<? super E> comparator) {
|
||||
checkNotNull(comparator);
|
||||
return Collector.of(
|
||||
() -> new ImmutableSortedSet.Builder<E>(comparator),
|
||||
ImmutableSortedSet.Builder::add,
|
||||
ImmutableSortedSet.Builder::combine,
|
||||
ImmutableSortedSet.Builder::build);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
static <E extends Enum<E>> Collector<E, ?, ImmutableSet<E>> toImmutableEnumSet() {
|
||||
return (Collector) EnumSetAccumulator.TO_IMMUTABLE_ENUM_SET;
|
||||
}
|
||||
|
||||
private static final class EnumSetAccumulator<E extends Enum<E>> {
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
static final Collector<Enum<?>, ?, ImmutableSet<? extends Enum<?>>> TO_IMMUTABLE_ENUM_SET =
|
||||
(Collector)
|
||||
Collector.<Enum, EnumSetAccumulator, ImmutableSet<?>>of(
|
||||
EnumSetAccumulator::new,
|
||||
EnumSetAccumulator::add,
|
||||
EnumSetAccumulator::combine,
|
||||
EnumSetAccumulator::toImmutableSet,
|
||||
Collector.Characteristics.UNORDERED);
|
||||
|
||||
private EnumSet<E> set;
|
||||
|
||||
void add(E e) {
|
||||
if (set == null) {
|
||||
set = EnumSet.of(e);
|
||||
} else {
|
||||
set.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
EnumSetAccumulator<E> combine(EnumSetAccumulator<E> other) {
|
||||
if (this.set == null) {
|
||||
return other;
|
||||
} else if (other.set == null) {
|
||||
return this;
|
||||
} else {
|
||||
this.set.addAll(other.set);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
ImmutableSet<E> toImmutableSet() {
|
||||
return (set == null) ? ImmutableSet.<E>of() : ImmutableEnumSet.asImmutable(set);
|
||||
}
|
||||
}
|
||||
|
||||
@GwtIncompatible
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
static <E extends Comparable<? super E>>
|
||||
Collector<Range<E>, ?, ImmutableRangeSet<E>> toImmutableRangeSet() {
|
||||
return (Collector) TO_IMMUTABLE_RANGE_SET;
|
||||
}
|
||||
|
||||
// Multisets
|
||||
|
||||
static <T, E> Collector<T, ?, ImmutableMultiset<E>> toImmutableMultiset(
|
||||
Function<? super T, ? extends E> elementFunction, ToIntFunction<? super T> countFunction) {
|
||||
checkNotNull(elementFunction);
|
||||
checkNotNull(countFunction);
|
||||
return Collector.of(
|
||||
LinkedHashMultiset::create,
|
||||
(multiset, t) ->
|
||||
multiset.add(checkNotNull(elementFunction.apply(t)), countFunction.applyAsInt(t)),
|
||||
(multiset1, multiset2) -> {
|
||||
multiset1.addAll(multiset2);
|
||||
return multiset1;
|
||||
},
|
||||
(Multiset<E> multiset) -> ImmutableMultiset.copyFromEntries(multiset.entrySet()));
|
||||
}
|
||||
|
||||
static <T, E, M extends Multiset<E>> Collector<T, ?, M> toMultiset(
|
||||
java.util.function.Function<? super T, E> elementFunction,
|
||||
java.util.function.ToIntFunction<? super T> countFunction,
|
||||
java.util.function.Supplier<M> multisetSupplier) {
|
||||
checkNotNull(elementFunction);
|
||||
checkNotNull(countFunction);
|
||||
checkNotNull(multisetSupplier);
|
||||
return Collector.of(
|
||||
multisetSupplier,
|
||||
(ms, t) -> ms.add(elementFunction.apply(t), countFunction.applyAsInt(t)),
|
||||
(ms1, ms2) -> {
|
||||
ms1.addAll(ms2);
|
||||
return ms1;
|
||||
});
|
||||
}
|
||||
|
||||
// Maps
|
||||
|
||||
static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction) {
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
return Collector.of(
|
||||
ImmutableMap.Builder<K, V>::new,
|
||||
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
|
||||
ImmutableMap.Builder::combine,
|
||||
ImmutableMap.Builder::build);
|
||||
ImmutableMap.Builder<K, V>::new,
|
||||
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
|
||||
ImmutableMap.Builder::combine,
|
||||
ImmutableMap.Builder::build);
|
||||
}
|
||||
|
||||
private static final Collector<Object, ?, ImmutableSet<Object>> TO_IMMUTABLE_SET =
|
||||
Collector.of(
|
||||
ImmutableSet::<Object>builder,
|
||||
ImmutableSet.Builder::add,
|
||||
ImmutableSet.Builder::combine,
|
||||
ImmutableSet.Builder::build);
|
||||
public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction,
|
||||
BinaryOperator<V> mergeFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
checkNotNull(mergeFunction);
|
||||
return Collectors.collectingAndThen(
|
||||
Collectors.toMap(keyFunction, valueFunction, mergeFunction, LinkedHashMap::new),
|
||||
ImmutableMap::copyOf);
|
||||
}
|
||||
|
||||
static <E> Collector<E, ?, ImmutableSet<E>> toImmutableSet() {
|
||||
return (Collector) TO_IMMUTABLE_SET;
|
||||
static <T, K, V> Collector<T, ?, ImmutableSortedMap<K, V>> toImmutableSortedMap(
|
||||
Comparator<? super K> comparator,
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction,
|
||||
BinaryOperator<V> mergeFunction) {
|
||||
checkNotNull(comparator);
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
checkNotNull(mergeFunction);
|
||||
return Collectors.collectingAndThen(
|
||||
Collectors.toMap(
|
||||
keyFunction, valueFunction, mergeFunction, () -> new TreeMap<K, V>(comparator)),
|
||||
ImmutableSortedMap::copyOfSorted);
|
||||
}
|
||||
|
||||
static <T, K, V> Collector<T, ?, ImmutableBiMap<K, V>> toImmutableBiMap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
return Collector.of(
|
||||
ImmutableBiMap.Builder<K, V>::new,
|
||||
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
|
||||
ImmutableBiMap.Builder::combine,
|
||||
ImmutableBiMap.Builder::build,
|
||||
new Collector.Characteristics[0]);
|
||||
}
|
||||
|
||||
static <T, K extends Enum<K>, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableEnumMap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
return Collector.of(
|
||||
() ->
|
||||
new EnumMapAccumulator<K, V>(
|
||||
(v1, v2) -> {
|
||||
throw new IllegalArgumentException("Multiple values for key: " + v1 + ", " + v2);
|
||||
}),
|
||||
(accum, t) -> {
|
||||
K key = checkNotNull(keyFunction.apply(t), "Null key for input %s", t);
|
||||
V newValue = checkNotNull(valueFunction.apply(t), "Null value for input %s", t);
|
||||
accum.put(key, newValue);
|
||||
},
|
||||
EnumMapAccumulator::combine,
|
||||
EnumMapAccumulator::toImmutableMap,
|
||||
Collector.Characteristics.UNORDERED);
|
||||
}
|
||||
|
||||
static <T, K extends Enum<K>, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableEnumMap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction,
|
||||
BinaryOperator<V> mergeFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
checkNotNull(mergeFunction);
|
||||
// not UNORDERED because we don't know if mergeFunction is commutative
|
||||
return Collector.of(
|
||||
() -> new EnumMapAccumulator<K, V>(mergeFunction),
|
||||
(accum, t) -> {
|
||||
K key = checkNotNull(keyFunction.apply(t), "Null key for input %s", t);
|
||||
V newValue = checkNotNull(valueFunction.apply(t), "Null value for input %s", t);
|
||||
accum.put(key, newValue);
|
||||
},
|
||||
EnumMapAccumulator::combine,
|
||||
EnumMapAccumulator::toImmutableMap);
|
||||
}
|
||||
|
||||
private static class EnumMapAccumulator<K extends Enum<K>, V> {
|
||||
private final BinaryOperator<V> mergeFunction;
|
||||
private EnumMap<K, V> map = null;
|
||||
|
||||
EnumMapAccumulator(BinaryOperator<V> mergeFunction) {
|
||||
this.mergeFunction = mergeFunction;
|
||||
}
|
||||
|
||||
void put(K key, V value) {
|
||||
if (map == null) {
|
||||
map = new EnumMap<>(key.getDeclaringClass());
|
||||
}
|
||||
map.merge(key, value, mergeFunction);
|
||||
}
|
||||
|
||||
EnumMapAccumulator<K, V> combine(EnumMapAccumulator<K, V> other) {
|
||||
if (this.map == null) {
|
||||
return other;
|
||||
} else if (other.map == null) {
|
||||
return this;
|
||||
} else {
|
||||
other.map.forEach(this::put);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
ImmutableMap<K, V> toImmutableMap() {
|
||||
return (map == null) ? ImmutableMap.<K, V>of() : ImmutableEnumMap.asImmutable(map);
|
||||
}
|
||||
}
|
||||
|
||||
@GwtIncompatible
|
||||
static <T, K extends Comparable<? super K>, V>
|
||||
Collector<T, ?, ImmutableRangeMap<K, V>> toImmutableRangeMap(
|
||||
Function<? super T, Range<K>> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
return Collector.of(
|
||||
ImmutableRangeMap::<K, V>builder,
|
||||
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
|
||||
ImmutableRangeMap.Builder::combine,
|
||||
ImmutableRangeMap.Builder::build);
|
||||
}
|
||||
|
||||
static <T, K, V> Collector<T, ?, ImmutableSortedMap<K, V>> toImmutableSortedMap(
|
||||
|
@ -92,43 +325,91 @@ final class CollectCollectors {
|
|||
ImmutableSortedMap.Builder::build,
|
||||
Collector.Characteristics.UNORDERED);
|
||||
}
|
||||
// Multimaps
|
||||
|
||||
static <E> Collector<E, ?, ImmutableSortedSet<E>> toImmutableSortedSet(
|
||||
Comparator<? super E> comparator) {
|
||||
checkNotNull(comparator);
|
||||
return Collector.of(
|
||||
() -> new ImmutableSortedSet.Builder<E>(comparator),
|
||||
ImmutableSortedSet.Builder::add,
|
||||
ImmutableSortedSet.Builder::combine,
|
||||
ImmutableSortedSet.Builder::build);
|
||||
}
|
||||
|
||||
@GwtIncompatible
|
||||
private static final Collector<Range<Comparable>, ?, ImmutableRangeSet<Comparable>>
|
||||
TO_IMMUTABLE_RANGE_SET =
|
||||
Collector.of(
|
||||
ImmutableRangeSet::<Comparable>builder,
|
||||
ImmutableRangeSet.Builder::add,
|
||||
ImmutableRangeSet.Builder::combine,
|
||||
ImmutableRangeSet.Builder::build);
|
||||
|
||||
@GwtIncompatible
|
||||
static <E extends Comparable<? super E>>
|
||||
Collector<Range<E>, ?, ImmutableRangeSet<E>> toImmutableRangeSet() {
|
||||
return (Collector) TO_IMMUTABLE_RANGE_SET;
|
||||
}
|
||||
|
||||
@GwtIncompatible
|
||||
static <T, K extends Comparable<? super K>, V>
|
||||
Collector<T, ?, ImmutableRangeMap<K, V>> toImmutableRangeMap(
|
||||
Function<? super T, Range<K>> keyFunction,
|
||||
static <T, K, V> Collector<T, ?, ImmutableListMultimap<K, V>> toImmutableListMultimap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction) {
|
||||
checkNotNull(keyFunction, "keyFunction");
|
||||
checkNotNull(valueFunction, "valueFunction");
|
||||
return Collector.of(
|
||||
ImmutableListMultimap::<K, V>builder,
|
||||
(builder, t) -> builder.put(keyFunction.apply(t), valueFunction.apply(t)),
|
||||
ImmutableListMultimap.Builder::combine,
|
||||
ImmutableListMultimap.Builder::build);
|
||||
}
|
||||
|
||||
static <T, K, V> Collector<T, ?, ImmutableListMultimap<K, V>> flatteningToImmutableListMultimap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends Stream<? extends V>> valuesFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valuesFunction);
|
||||
return Collectors.collectingAndThen(
|
||||
flatteningToMultimap(
|
||||
input -> checkNotNull(keyFunction.apply(input)),
|
||||
input -> valuesFunction.apply(input).peek(Preconditions::checkNotNull),
|
||||
MultimapBuilder.linkedHashKeys().arrayListValues()::<K, V>build),
|
||||
ImmutableListMultimap::copyOf);
|
||||
}
|
||||
|
||||
static <T, K, V> Collector<T, ?, ImmutableSetMultimap<K, V>> toImmutableSetMultimap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction) {
|
||||
checkNotNull(keyFunction, "keyFunction");
|
||||
checkNotNull(valueFunction, "valueFunction");
|
||||
return Collector.of(
|
||||
ImmutableSetMultimap::<K, V>builder,
|
||||
(builder, t) -> builder.put(keyFunction.apply(t), valueFunction.apply(t)),
|
||||
ImmutableSetMultimap.Builder::combine,
|
||||
ImmutableSetMultimap.Builder::build);
|
||||
}
|
||||
|
||||
static <T, K, V> Collector<T, ?, ImmutableSetMultimap<K, V>> flatteningToImmutableSetMultimap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends Stream<? extends V>> valuesFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valuesFunction);
|
||||
return Collectors.collectingAndThen(
|
||||
flatteningToMultimap(
|
||||
input -> checkNotNull(keyFunction.apply(input)),
|
||||
input -> valuesFunction.apply(input).peek(Preconditions::checkNotNull),
|
||||
MultimapBuilder.linkedHashKeys().linkedHashSetValues()::<K, V>build),
|
||||
ImmutableSetMultimap::copyOf);
|
||||
}
|
||||
|
||||
static <T, K, V, M extends Multimap<K, V>> Collector<T, ?, M> toMultimap(
|
||||
java.util.function.Function<? super T, ? extends K> keyFunction,
|
||||
java.util.function.Function<? super T, ? extends V> valueFunction,
|
||||
java.util.function.Supplier<M> multimapSupplier) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
checkNotNull(multimapSupplier);
|
||||
return Collector.of(
|
||||
ImmutableRangeMap::<K, V>builder,
|
||||
(builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
|
||||
ImmutableRangeMap.Builder::combine,
|
||||
ImmutableRangeMap.Builder::build);
|
||||
multimapSupplier,
|
||||
(multimap, input) -> multimap.put(keyFunction.apply(input), valueFunction.apply(input)),
|
||||
(multimap1, multimap2) -> {
|
||||
multimap1.putAll(multimap2);
|
||||
return multimap1;
|
||||
});
|
||||
}
|
||||
|
||||
static <T, K, V, M extends Multimap<K, V>> Collector<T, ?, M> flatteningToMultimap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends Stream<? extends V>> valueFunction,
|
||||
Supplier<M> multimapSupplier) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
checkNotNull(multimapSupplier);
|
||||
return Collector.of(
|
||||
multimapSupplier,
|
||||
(multimap, input) -> {
|
||||
K key = keyFunction.apply(input);
|
||||
Collection<V> valuesForKey = multimap.get(key);
|
||||
valueFunction.apply(input).forEachOrdered(valuesForKey::add);
|
||||
},
|
||||
(multimap1, multimap2) -> {
|
||||
multimap1.putAll(multimap2);
|
||||
return multimap1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -352,11 +352,6 @@ public final class Collections2 {
|
|||
return new StringBuilder((int) Math.min(size * 8L, Ints.MAX_POWER_OF_TWO));
|
||||
}
|
||||
|
||||
/** Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557 */
|
||||
static <T> Collection<T> cast(Iterable<T> iterable) {
|
||||
return (Collection<T>) iterable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Collection} of all the permutations of the specified {@link Iterable}.
|
||||
*
|
||||
|
|
|
@ -190,4 +190,79 @@ public final class Comparators {
|
|||
checkNotNull(valueComparator);
|
||||
return Comparator.comparing(o -> o.orElse(null), Comparator.nullsLast(valueComparator));
|
||||
}
|
||||
/**
|
||||
* Returns the minimum of the two values. If the values compare as 0, the first is returned.
|
||||
*
|
||||
* <p>The recommended solution for finding the {@code minimum} of some values depends on the type
|
||||
* of your data and the number of elements you have. Read more in the Guava User Guide article on
|
||||
* <a href="https://github.com/google/guava/wiki/CollectionUtilitiesExplained#comparators">{@code
|
||||
* Comparators}</a>.
|
||||
*
|
||||
* @param a first value to compare, returned if less than or equal to b.
|
||||
* @param b second value to compare.
|
||||
* @throws ClassCastException if the parameters are not <i>mutually comparable</i>.
|
||||
* @since 30.0
|
||||
*/
|
||||
@Beta
|
||||
public static <T extends Comparable<? super T>> T min(T a, T b) {
|
||||
return (a.compareTo(b) <= 0) ? a : b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum of the two values, according to the given comparator. If the values compare
|
||||
* as equal, the first is returned.
|
||||
*
|
||||
* <p>The recommended solution for finding the {@code minimum} of some values depends on the type
|
||||
* of your data and the number of elements you have. Read more in the Guava User Guide article on
|
||||
* <a href="https://github.com/google/guava/wiki/CollectionUtilitiesExplained#comparators">{@code
|
||||
* Comparators}</a>.
|
||||
*
|
||||
* @param a first value to compare, returned if less than or equal to b
|
||||
* @param b second value to compare.
|
||||
* @throws ClassCastException if the parameters are not <i>mutually comparable</i> using the given
|
||||
* comparator.
|
||||
* @since 30.0
|
||||
*/
|
||||
@Beta
|
||||
public static <T> T min(T a, T b, Comparator<T> comparator) {
|
||||
return (comparator.compare(a, b) <= 0) ? a : b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum of the two values. If the values compare as 0, the first is returned.
|
||||
*
|
||||
* <p>The recommended solution for finding the {@code maximum} of some values depends on the type
|
||||
* of your data and the number of elements you have. Read more in the Guava User Guide article on
|
||||
* <a href="https://github.com/google/guava/wiki/CollectionUtilitiesExplained#comparators">{@code
|
||||
* Comparators}</a>.
|
||||
*
|
||||
* @param a first value to compare, returned if greater than or equal to b.
|
||||
* @param b second value to compare.
|
||||
* @throws ClassCastException if the parameters are not <i>mutually comparable</i>.
|
||||
* @since 30.0
|
||||
*/
|
||||
@Beta
|
||||
public static <T extends Comparable<? super T>> T max(T a, T b) {
|
||||
return (a.compareTo(b) >= 0) ? a : b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum of the two values, according to the given comparator. If the values compare
|
||||
* as equal, the first is returned.
|
||||
*
|
||||
* <p>The recommended solution for finding the {@code maximum} of some values depends on the type
|
||||
* of your data and the number of elements you have. Read more in the Guava User Guide article on
|
||||
* <a href="https://github.com/google/guava/wiki/CollectionUtilitiesExplained#comparators">{@code
|
||||
* Comparators}</a>.
|
||||
*
|
||||
* @param a first value to compare, returned if greater than or equal to b.
|
||||
* @param b second value to compare.
|
||||
* @throws ClassCastException if the parameters are not <i>mutually comparable</i> using the given
|
||||
* comparator.
|
||||
* @since 30.0
|
||||
*/
|
||||
@Beta
|
||||
public static <T> T max(T a, T b, Comparator<T> comparator) {
|
||||
return (comparator.compare(a, b) >= 0) ? a : b;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,15 +191,14 @@ public abstract class ContiguousSet<C extends Comparable> extends ImmutableSorte
|
|||
/*
|
||||
* These methods perform most headSet, subSet, and tailSet logic, besides parameter validation.
|
||||
*/
|
||||
// TODO(kevinb): we can probably make these real @Overrides now
|
||||
/* @Override */
|
||||
@SuppressWarnings("MissingOverride") // Supermethod does not exist under GWT.
|
||||
abstract ContiguousSet<C> headSetImpl(C toElement, boolean inclusive);
|
||||
|
||||
/* @Override */
|
||||
@SuppressWarnings("MissingOverride") // Supermethod does not exist under GWT.
|
||||
abstract ContiguousSet<C> subSetImpl(
|
||||
C fromElement, boolean fromInclusive, C toElement, boolean toInclusive);
|
||||
|
||||
/* @Override */
|
||||
@SuppressWarnings("MissingOverride") // Supermethod does not exist under GWT.
|
||||
abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
|
||||
|
||||
/**
|
||||
|
|
|
@ -786,7 +786,7 @@ public abstract class FluentIterable<E> implements Iterable<E> {
|
|||
checkNotNull(collection);
|
||||
Iterable<E> iterable = getDelegate();
|
||||
if (iterable instanceof Collection) {
|
||||
collection.addAll(Collections2.cast(iterable));
|
||||
collection.addAll((Collection<E>) iterable);
|
||||
} else {
|
||||
for (E item : iterable) {
|
||||
collection.add(item);
|
||||
|
|
|
@ -76,8 +76,8 @@ public abstract class ForwardingMap<K, V> extends ForwardingObject implements Ma
|
|||
|
||||
|
||||
@Override
|
||||
public V remove(Object object) {
|
||||
return delegate().remove(object);
|
||||
public V remove(Object key) {
|
||||
return delegate().remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -413,15 +413,14 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableBiMapFauxverideShim<
|
|||
* <p>Since the bimap is immutable, ImmutableBiMap doesn't require special logic for keeping the
|
||||
* bimap and its inverse in sync during serialization, the way AbstractBiMap does.
|
||||
*/
|
||||
private static class SerializedForm extends ImmutableMap.SerializedForm {
|
||||
SerializedForm(ImmutableBiMap<?, ?> bimap) {
|
||||
private static class SerializedForm<K, V> extends ImmutableMap.SerializedForm<K, V> {
|
||||
SerializedForm(ImmutableBiMap<K, V> bimap) {
|
||||
super(bimap);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object readResolve() {
|
||||
Builder<Object, Object> builder = new Builder<>();
|
||||
return createMap(builder);
|
||||
Builder<K, V> makeBuilder(int size) {
|
||||
return new Builder<>();
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 0;
|
||||
|
@ -429,6 +428,6 @@ public abstract class ImmutableBiMap<K, V> extends ImmutableBiMapFauxverideShim<
|
|||
|
||||
@Override
|
||||
Object writeReplace() {
|
||||
return new SerializedForm(this);
|
||||
return new SerializedForm<>(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
|
@ -83,13 +82,7 @@ public class ImmutableListMultimap<K, V> extends ImmutableMultimap<K, V>
|
|||
public static <T, K, V> Collector<T, ?, ImmutableListMultimap<K, V>> toImmutableListMultimap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction) {
|
||||
checkNotNull(keyFunction, "keyFunction");
|
||||
checkNotNull(valueFunction, "valueFunction");
|
||||
return Collector.of(
|
||||
ImmutableListMultimap::<K, V>builder,
|
||||
(builder, t) -> builder.put(keyFunction.apply(t), valueFunction.apply(t)),
|
||||
ImmutableListMultimap.Builder::combine,
|
||||
ImmutableListMultimap.Builder::build);
|
||||
return CollectCollectors.toImmutableListMultimap(keyFunction, valueFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,14 +120,7 @@ public class ImmutableListMultimap<K, V> extends ImmutableMultimap<K, V>
|
|||
Collector<T, ?, ImmutableListMultimap<K, V>> flatteningToImmutableListMultimap(
|
||||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends Stream<? extends V>> valuesFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valuesFunction);
|
||||
return Collectors.collectingAndThen(
|
||||
Multimaps.flatteningToMultimap(
|
||||
input -> checkNotNull(keyFunction.apply(input)),
|
||||
input -> valuesFunction.apply(input).peek(Preconditions::checkNotNull),
|
||||
MultimapBuilder.linkedHashKeys().arrayListValues()::<K, V>build),
|
||||
ImmutableListMultimap::copyOf);
|
||||
return CollectCollectors.flatteningToImmutableListMultimap(keyFunction, valuesFunction);
|
||||
}
|
||||
|
||||
/** Returns the empty multimap. */
|
||||
|
|
|
@ -36,7 +36,6 @@ import java.util.Collections;
|
|||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.Spliterator;
|
||||
|
@ -96,12 +95,7 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
|
|||
Function<? super T, ? extends K> keyFunction,
|
||||
Function<? super T, ? extends V> valueFunction,
|
||||
BinaryOperator<V> mergeFunction) {
|
||||
checkNotNull(keyFunction);
|
||||
checkNotNull(valueFunction);
|
||||
checkNotNull(mergeFunction);
|
||||
return Collectors.collectingAndThen(
|
||||
Collectors.toMap(keyFunction, valueFunction, mergeFunction, LinkedHashMap::new),
|
||||
ImmutableMap::copyOf);
|
||||
return CollectCollectors.toImmutableMap(keyFunction, valueFunction, mergeFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -889,37 +883,85 @@ public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {
|
|||
* reconstructed using public factory methods. This ensures that the implementation types remain
|
||||
* as implementation details.
|
||||
*/
|
||||
static class SerializedForm implements Serializable {
|
||||
private final Object[] keys;
|
||||
private final Object[] values;
|
||||
static class SerializedForm<K, V> implements Serializable {
|
||||
// This object retains references to collections returned by keySet() and value(). This saves
|
||||
// bytes when the both the map and its keySet or value collection are written to the same
|
||||
// instance of ObjectOutputStream.
|
||||
|
||||
SerializedForm(ImmutableMap<?, ?> map) {
|
||||
keys = new Object[map.size()];
|
||||
values = new Object[map.size()];
|
||||
int i = 0;
|
||||
for (Entry<?, ?> entry : map.entrySet()) {
|
||||
keys[i] = entry.getKey();
|
||||
values[i] = entry.getValue();
|
||||
i++;
|
||||
// TODO(b/160980469): remove support for the old serialization format after some time
|
||||
private static final boolean USE_LEGACY_SERIALIZATION = true;
|
||||
|
||||
private final Object keys;
|
||||
private final Object values;
|
||||
|
||||
SerializedForm(ImmutableMap<K, V> map) {
|
||||
if (USE_LEGACY_SERIALIZATION) {
|
||||
Object[] keys = new Object[map.size()];
|
||||
Object[] values = new Object[map.size()];
|
||||
int i = 0;
|
||||
for (Entry<?, ?> entry : map.entrySet()) {
|
||||
keys[i] = entry.getKey();
|
||||
values[i] = entry.getValue();
|
||||
i++;
|
||||
}
|
||||
this.keys = keys;
|
||||
this.values = values;
|
||||
return;
|
||||
}
|
||||
this.keys = map.keySet();
|
||||
this.values = map.values();
|
||||
}
|
||||
|
||||
Object readResolve() {
|
||||
Builder<Object, Object> builder = new Builder<>(keys.length);
|
||||
return createMap(builder);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Object readResolve() {
|
||||
if (!(this.keys instanceof ImmutableSet)) {
|
||||
return legacyReadResolve();
|
||||
}
|
||||
|
||||
ImmutableSet<K> keySet = (ImmutableSet<K>) this.keys;
|
||||
ImmutableCollection<V> values = (ImmutableCollection<V>) this.values;
|
||||
|
||||
Builder<K, V> builder = makeBuilder(keySet.size());
|
||||
|
||||
UnmodifiableIterator<K> keyIter = keySet.iterator();
|
||||
UnmodifiableIterator<V> valueIter = values.iterator();
|
||||
|
||||
while (keyIter.hasNext()) {
|
||||
builder.put(keyIter.next(), valueIter.next());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||