1278 lines
42 KiB
Java
1278 lines
42 KiB
Java
/*
|
|
* Copyright (C) 2008 The Guava Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.google.common.collect;
|
|
|
|
import static com.google.common.collect.testing.Helpers.mapEntry;
|
|
import static com.google.common.testing.SerializableTester.reserialize;
|
|
import static com.google.common.truth.Truth.assertThat;
|
|
import static com.google.common.truth.Truth.assertWithMessage;
|
|
|
|
import com.google.common.annotations.GwtCompatible;
|
|
import com.google.common.annotations.GwtIncompatible;
|
|
import com.google.common.base.Equivalence;
|
|
import com.google.common.base.Joiner;
|
|
import com.google.common.collect.ImmutableMap.Builder;
|
|
import com.google.common.collect.testing.AnEnum;
|
|
import com.google.common.collect.testing.CollectionTestSuiteBuilder;
|
|
import com.google.common.collect.testing.ListTestSuiteBuilder;
|
|
import com.google.common.collect.testing.MapInterfaceTest;
|
|
import com.google.common.collect.testing.MapTestSuiteBuilder;
|
|
import com.google.common.collect.testing.MinimalSet;
|
|
import com.google.common.collect.testing.SampleElements.Colliders;
|
|
import com.google.common.collect.testing.SampleElements.Unhashables;
|
|
import com.google.common.collect.testing.TestStringMapGenerator;
|
|
import com.google.common.collect.testing.UnhashableObject;
|
|
import com.google.common.collect.testing.features.CollectionFeature;
|
|
import com.google.common.collect.testing.features.CollectionSize;
|
|
import com.google.common.collect.testing.features.MapFeature;
|
|
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfEntriesGenerator;
|
|
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfEnumMapGenerator;
|
|
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfGenerator;
|
|
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapEntryListGenerator;
|
|
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapGenerator;
|
|
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapKeyListGenerator;
|
|
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapUnhashableValuesGenerator;
|
|
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapValueListGenerator;
|
|
import com.google.common.collect.testing.google.MapGenerators.ImmutableMapValuesAsSingletonSetGenerator;
|
|
import com.google.common.testing.CollectorTester;
|
|
import com.google.common.testing.EqualsTester;
|
|
import com.google.common.testing.NullPointerTester;
|
|
import com.google.common.testing.SerializableTester;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.ObjectOutputStream;
|
|
import java.io.Serializable;
|
|
import java.util.AbstractMap;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.EnumMap;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
import java.util.Set;
|
|
import java.util.stream.Collector;
|
|
import java.util.stream.Stream;
|
|
import junit.framework.Test;
|
|
import junit.framework.TestCase;
|
|
import junit.framework.TestSuite;
|
|
|
|
/**
|
|
* Tests for {@link ImmutableMap}.
|
|
*
|
|
* @author Kevin Bourrillion
|
|
* @author Jesse Wilson
|
|
*/
|
|
@GwtCompatible(emulated = true)
|
|
public class ImmutableMapTest extends TestCase {
|
|
|
|
@GwtIncompatible // suite
|
|
public static Test suite() {
|
|
TestSuite suite = new TestSuite();
|
|
suite.addTestSuite(ImmutableMapTest.class);
|
|
suite.addTestSuite(FloodingTest.class);
|
|
|
|
suite.addTest(
|
|
MapTestSuiteBuilder.using(new ImmutableMapGenerator())
|
|
.withFeatures(
|
|
CollectionSize.ANY,
|
|
CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
|
|
CollectionFeature.KNOWN_ORDER,
|
|
MapFeature.REJECTS_DUPLICATES_AT_CREATION,
|
|
CollectionFeature.ALLOWS_NULL_QUERIES)
|
|
.named("ImmutableMap")
|
|
.createTestSuite());
|
|
|
|
suite.addTest(
|
|
MapTestSuiteBuilder.using(
|
|
new TestStringMapGenerator() {
|
|
@Override
|
|
protected Map<String, String> create(Entry<String, String>[] entries) {
|
|
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
|
|
builder.putAll(Arrays.asList(entries));
|
|
return builder.buildJdkBacked();
|
|
}
|
|
})
|
|
.withFeatures(
|
|
CollectionSize.ANY,
|
|
CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
|
|
CollectionFeature.KNOWN_ORDER,
|
|
MapFeature.REJECTS_DUPLICATES_AT_CREATION,
|
|
CollectionFeature.ALLOWS_NULL_QUERIES)
|
|
.named("ImmutableMap [JDK backed]")
|
|
.createTestSuite());
|
|
|
|
suite.addTest(
|
|
MapTestSuiteBuilder.using(new ImmutableMapCopyOfGenerator())
|
|
.withFeatures(
|
|
CollectionSize.ANY,
|
|
CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
|
|
CollectionFeature.KNOWN_ORDER,
|
|
CollectionFeature.ALLOWS_NULL_QUERIES)
|
|
.named("ImmutableMap.copyOf[Map]")
|
|
.createTestSuite());
|
|
|
|
suite.addTest(
|
|
MapTestSuiteBuilder.using(new ImmutableMapCopyOfEntriesGenerator())
|
|
.withFeatures(
|
|
CollectionSize.ANY,
|
|
MapFeature.REJECTS_DUPLICATES_AT_CREATION,
|
|
CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
|
|
CollectionFeature.KNOWN_ORDER,
|
|
CollectionFeature.ALLOWS_NULL_QUERIES)
|
|
.named("ImmutableMap.copyOf[Iterable<Entry>]")
|
|
.createTestSuite());
|
|
|
|
suite.addTest(
|
|
MapTestSuiteBuilder.using(new ImmutableMapCopyOfEnumMapGenerator())
|
|
.withFeatures(
|
|
CollectionSize.ANY,
|
|
CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
|
|
CollectionFeature.KNOWN_ORDER,
|
|
CollectionFeature.ALLOWS_NULL_QUERIES)
|
|
.named("ImmutableMap.copyOf[EnumMap]")
|
|
.createTestSuite());
|
|
|
|
suite.addTest(
|
|
MapTestSuiteBuilder.using(new ImmutableMapValuesAsSingletonSetGenerator())
|
|
.withFeatures(
|
|
CollectionSize.ANY,
|
|
MapFeature.REJECTS_DUPLICATES_AT_CREATION,
|
|
CollectionFeature.KNOWN_ORDER,
|
|
CollectionFeature.ALLOWS_NULL_QUERIES)
|
|
.named("ImmutableMap.asMultimap.asMap")
|
|
.createTestSuite());
|
|
|
|
suite.addTest(
|
|
CollectionTestSuiteBuilder.using(new ImmutableMapUnhashableValuesGenerator())
|
|
.withFeatures(
|
|
CollectionSize.ANY,
|
|
CollectionFeature.KNOWN_ORDER,
|
|
CollectionFeature.ALLOWS_NULL_QUERIES)
|
|
.named("ImmutableMap.values, unhashable")
|
|
.createTestSuite());
|
|
|
|
suite.addTest(
|
|
ListTestSuiteBuilder.using(new ImmutableMapKeyListGenerator())
|
|
.named("ImmutableMap.keySet.asList")
|
|
.withFeatures(
|
|
CollectionSize.ANY,
|
|
CollectionFeature.SERIALIZABLE,
|
|
CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
|
|
CollectionFeature.ALLOWS_NULL_QUERIES)
|
|
.createTestSuite());
|
|
|
|
suite.addTest(
|
|
ListTestSuiteBuilder.using(new ImmutableMapEntryListGenerator())
|
|
.named("ImmutableMap.entrySet.asList")
|
|
.withFeatures(
|
|
CollectionSize.ANY,
|
|
CollectionFeature.SERIALIZABLE,
|
|
CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
|
|
CollectionFeature.ALLOWS_NULL_QUERIES)
|
|
.createTestSuite());
|
|
|
|
suite.addTest(
|
|
ListTestSuiteBuilder.using(new ImmutableMapValueListGenerator())
|
|
.named("ImmutableMap.values.asList")
|
|
.withFeatures(
|
|
CollectionSize.ANY,
|
|
CollectionFeature.SERIALIZABLE,
|
|
CollectionFeature.ALLOWS_NULL_QUERIES)
|
|
.createTestSuite());
|
|
|
|
return suite;
|
|
}
|
|
|
|
public abstract static class AbstractMapTests<K, V> extends MapInterfaceTest<K, V> {
|
|
public AbstractMapTests() {
|
|
super(false, false, false, false, false);
|
|
}
|
|
|
|
@Override
|
|
protected Map<K, V> makeEmptyMap() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
private static final Joiner joiner = Joiner.on(", ");
|
|
|
|
@Override
|
|
protected void assertMoreInvariants(Map<K, V> map) {
|
|
// TODO: can these be moved to MapInterfaceTest?
|
|
for (Entry<K, V> entry : map.entrySet()) {
|
|
assertEquals(entry.getKey() + "=" + entry.getValue(), entry.toString());
|
|
}
|
|
|
|
assertEquals("{" + joiner.join(map.entrySet()) + "}", map.toString());
|
|
assertEquals("[" + joiner.join(map.entrySet()) + "]", map.entrySet().toString());
|
|
assertEquals("[" + joiner.join(map.keySet()) + "]", map.keySet().toString());
|
|
assertEquals("[" + joiner.join(map.values()) + "]", map.values().toString());
|
|
|
|
assertEquals(MinimalSet.from(map.entrySet()), map.entrySet());
|
|
assertEquals(Sets.newHashSet(map.keySet()), map.keySet());
|
|
}
|
|
}
|
|
|
|
public static class MapTests extends AbstractMapTests<String, Integer> {
|
|
@Override
|
|
protected Map<String, Integer> makeEmptyMap() {
|
|
return ImmutableMap.of();
|
|
}
|
|
|
|
@Override
|
|
protected Map<String, Integer> makePopulatedMap() {
|
|
return ImmutableMap.of("one", 1, "two", 2, "three", 3);
|
|
}
|
|
|
|
@Override
|
|
protected String getKeyNotInPopulatedMap() {
|
|
return "minus one";
|
|
}
|
|
|
|
@Override
|
|
protected Integer getValueNotInPopulatedMap() {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
public static class SingletonMapTests extends AbstractMapTests<String, Integer> {
|
|
@Override
|
|
protected Map<String, Integer> makePopulatedMap() {
|
|
return ImmutableMap.of("one", 1);
|
|
}
|
|
|
|
@Override
|
|
protected String getKeyNotInPopulatedMap() {
|
|
return "minus one";
|
|
}
|
|
|
|
@Override
|
|
protected Integer getValueNotInPopulatedMap() {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
@GwtIncompatible // SerializableTester
|
|
public static class ReserializedMapTests extends AbstractMapTests<String, Integer> {
|
|
@Override
|
|
protected Map<String, Integer> makePopulatedMap() {
|
|
return SerializableTester.reserialize(ImmutableMap.of("one", 1, "two", 2, "three", 3));
|
|
}
|
|
|
|
@Override
|
|
protected String getKeyNotInPopulatedMap() {
|
|
return "minus one";
|
|
}
|
|
|
|
@Override
|
|
protected Integer getValueNotInPopulatedMap() {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
public static class MapTestsWithBadHashes extends AbstractMapTests<Object, Integer> {
|
|
|
|
@Override
|
|
protected Map<Object, Integer> makeEmptyMap() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
protected Map<Object, Integer> makePopulatedMap() {
|
|
Colliders colliders = new Colliders();
|
|
return ImmutableMap.of(
|
|
colliders.e0(), 0,
|
|
colliders.e1(), 1,
|
|
colliders.e2(), 2,
|
|
colliders.e3(), 3);
|
|
}
|
|
|
|
@Override
|
|
protected Object getKeyNotInPopulatedMap() {
|
|
return new Colliders().e4();
|
|
}
|
|
|
|
@Override
|
|
protected Integer getValueNotInPopulatedMap() {
|
|
return 4;
|
|
}
|
|
}
|
|
|
|
@GwtIncompatible // GWT's ImmutableMap emulation is backed by java.util.HashMap.
|
|
public static class MapTestsWithUnhashableValues
|
|
extends AbstractMapTests<Integer, UnhashableObject> {
|
|
@Override
|
|
protected Map<Integer, UnhashableObject> makeEmptyMap() {
|
|
return ImmutableMap.of();
|
|
}
|
|
|
|
@Override
|
|
protected Map<Integer, UnhashableObject> makePopulatedMap() {
|
|
Unhashables unhashables = new Unhashables();
|
|
return ImmutableMap.of(0, unhashables.e0(), 1, unhashables.e1(), 2, unhashables.e2());
|
|
}
|
|
|
|
@Override
|
|
protected Integer getKeyNotInPopulatedMap() {
|
|
return 3;
|
|
}
|
|
|
|
@Override
|
|
protected UnhashableObject getValueNotInPopulatedMap() {
|
|
return new Unhashables().e3();
|
|
}
|
|
}
|
|
|
|
@GwtIncompatible // GWT's ImmutableMap emulation is backed by java.util.HashMap.
|
|
public static class MapTestsWithSingletonUnhashableValue extends MapTestsWithUnhashableValues {
|
|
@Override
|
|
protected Map<Integer, UnhashableObject> makePopulatedMap() {
|
|
Unhashables unhashables = new Unhashables();
|
|
return ImmutableMap.of(0, unhashables.e0());
|
|
}
|
|
}
|
|
|
|
public static class CreationTests extends TestCase {
|
|
public void testEmptyBuilder() {
|
|
ImmutableMap<String, Integer> map = new Builder<String, Integer>().build();
|
|
assertEquals(Collections.<String, Integer>emptyMap(), map);
|
|
}
|
|
|
|
public void testSingletonBuilder() {
|
|
ImmutableMap<String, Integer> map = new Builder<String, Integer>().put("one", 1).build();
|
|
assertMapEquals(map, "one", 1);
|
|
}
|
|
|
|
public void testBuilder() {
|
|
ImmutableMap<String, Integer> map =
|
|
new Builder<String, Integer>()
|
|
.put("one", 1)
|
|
.put("two", 2)
|
|
.put("three", 3)
|
|
.put("four", 4)
|
|
.put("five", 5)
|
|
.build();
|
|
assertMapEquals(map, "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
|
|
}
|
|
|
|
@GwtIncompatible
|
|
public void testBuilderExactlySizedReusesArray() {
|
|
ImmutableMap.Builder<Integer, Integer> builder = ImmutableMap.builderWithExpectedSize(10);
|
|
Entry<Integer, Integer>[] builderArray = builder.entries;
|
|
for (int i = 0; i < 10; i++) {
|
|
builder.put(i, i);
|
|
}
|
|
Entry<Integer, Integer>[] builderArrayAfterPuts = builder.entries;
|
|
RegularImmutableMap<Integer, Integer> map =
|
|
(RegularImmutableMap<Integer, Integer>) builder.build();
|
|
Entry<Integer, Integer>[] mapInternalArray = map.entries;
|
|
assertSame(builderArray, builderArrayAfterPuts);
|
|
assertSame(builderArray, mapInternalArray);
|
|
}
|
|
|
|
public void testBuilder_orderEntriesByValue() {
|
|
ImmutableMap<String, Integer> map =
|
|
new Builder<String, Integer>()
|
|
.orderEntriesByValue(Ordering.natural())
|
|
.put("three", 3)
|
|
.put("one", 1)
|
|
.put("five", 5)
|
|
.put("four", 4)
|
|
.put("two", 2)
|
|
.build();
|
|
assertMapEquals(map, "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
|
|
}
|
|
|
|
public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
|
|
Builder<String, Integer> builder =
|
|
new Builder<String, Integer>(2).put("four", 4).put("one", 1);
|
|
ImmutableMap<String, Integer> keyOrdered = builder.build();
|
|
ImmutableMap<String, Integer> valueOrdered =
|
|
builder.orderEntriesByValue(Ordering.natural()).build();
|
|
assertMapEquals(keyOrdered, "four", 4, "one", 1);
|
|
assertMapEquals(valueOrdered, "one", 1, "four", 4);
|
|
}
|
|
|
|
public void testBuilder_orderEntriesByValue_usedTwiceFails() {
|
|
ImmutableMap.Builder<String, Integer> builder =
|
|
new Builder<String, Integer>().orderEntriesByValue(Ordering.natural());
|
|
try {
|
|
builder.orderEntriesByValue(Ordering.natural());
|
|
fail("Expected IllegalStateException");
|
|
} catch (IllegalStateException expected) {
|
|
}
|
|
}
|
|
|
|
public void testBuilder_withImmutableEntry() {
|
|
ImmutableMap<String, Integer> map =
|
|
new Builder<String, Integer>().put(Maps.immutableEntry("one", 1)).build();
|
|
assertMapEquals(map, "one", 1);
|
|
}
|
|
|
|
public void testBuilder_withImmutableEntryAndNullContents() {
|
|
Builder<String, Integer> builder = new Builder<>();
|
|
try {
|
|
builder.put(Maps.immutableEntry("one", (Integer) null));
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
try {
|
|
builder.put(Maps.immutableEntry((String) null, 1));
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
}
|
|
|
|
private static class StringHolder {
|
|
String string;
|
|
}
|
|
|
|
public void testBuilder_withMutableEntry() {
|
|
ImmutableMap.Builder<String, Integer> builder = new Builder<>();
|
|
final StringHolder holder = new StringHolder();
|
|
holder.string = "one";
|
|
Entry<String, Integer> entry =
|
|
new AbstractMapEntry<String, Integer>() {
|
|
@Override
|
|
public String getKey() {
|
|
return holder.string;
|
|
}
|
|
|
|
@Override
|
|
public Integer getValue() {
|
|
return 1;
|
|
}
|
|
};
|
|
|
|
builder.put(entry);
|
|
holder.string = "two";
|
|
assertMapEquals(builder.build(), "one", 1);
|
|
}
|
|
|
|
public void testBuilderPutAllWithEmptyMap() {
|
|
ImmutableMap<String, Integer> map =
|
|
new Builder<String, Integer>().putAll(Collections.<String, Integer>emptyMap()).build();
|
|
assertEquals(Collections.<String, Integer>emptyMap(), map);
|
|
}
|
|
|
|
public void testBuilderPutAll() {
|
|
Map<String, Integer> toPut = new LinkedHashMap<>();
|
|
toPut.put("one", 1);
|
|
toPut.put("two", 2);
|
|
toPut.put("three", 3);
|
|
Map<String, Integer> moreToPut = new LinkedHashMap<>();
|
|
moreToPut.put("four", 4);
|
|
moreToPut.put("five", 5);
|
|
|
|
ImmutableMap<String, Integer> map =
|
|
new Builder<String, Integer>().putAll(toPut).putAll(moreToPut).build();
|
|
assertMapEquals(map, "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
|
|
}
|
|
|
|
public void testBuilderReuse() {
|
|
Builder<String, Integer> builder = new Builder<>();
|
|
ImmutableMap<String, Integer> mapOne = builder.put("one", 1).put("two", 2).build();
|
|
ImmutableMap<String, Integer> mapTwo = builder.put("three", 3).put("four", 4).build();
|
|
|
|
assertMapEquals(mapOne, "one", 1, "two", 2);
|
|
assertMapEquals(mapTwo, "one", 1, "two", 2, "three", 3, "four", 4);
|
|
}
|
|
|
|
public void testBuilderPutNullKeyFailsAtomically() {
|
|
Builder<String, Integer> builder = new Builder<>();
|
|
try {
|
|
builder.put(null, 1);
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
builder.put("foo", 2);
|
|
assertMapEquals(builder.build(), "foo", 2);
|
|
}
|
|
|
|
public void testBuilderPutImmutableEntryWithNullKeyFailsAtomically() {
|
|
Builder<String, Integer> builder = new Builder<>();
|
|
try {
|
|
builder.put(Maps.immutableEntry((String) null, 1));
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
builder.put("foo", 2);
|
|
assertMapEquals(builder.build(), "foo", 2);
|
|
}
|
|
|
|
// for GWT compatibility
|
|
static class SimpleEntry<K, V> extends AbstractMapEntry<K, V> {
|
|
public K key;
|
|
public V value;
|
|
|
|
SimpleEntry(K key, V value) {
|
|
this.key = key;
|
|
this.value = value;
|
|
}
|
|
|
|
@Override
|
|
public K getKey() {
|
|
return key;
|
|
}
|
|
|
|
@Override
|
|
public V getValue() {
|
|
return value;
|
|
}
|
|
}
|
|
|
|
public void testBuilderPutMutableEntryWithNullKeyFailsAtomically() {
|
|
Builder<String, Integer> builder = new Builder<>();
|
|
try {
|
|
builder.put(new SimpleEntry<String, Integer>(null, 1));
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
builder.put("foo", 2);
|
|
assertMapEquals(builder.build(), "foo", 2);
|
|
}
|
|
|
|
public void testBuilderPutNullKey() {
|
|
Builder<String, Integer> builder = new Builder<>();
|
|
try {
|
|
builder.put(null, 1);
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
}
|
|
|
|
public void testBuilderPutNullValue() {
|
|
Builder<String, Integer> builder = new Builder<>();
|
|
try {
|
|
builder.put("one", null);
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
}
|
|
|
|
public void testBuilderPutNullKeyViaPutAll() {
|
|
Builder<String, Integer> builder = new Builder<>();
|
|
try {
|
|
builder.putAll(Collections.<String, Integer>singletonMap(null, 1));
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
}
|
|
|
|
public void testBuilderPutNullValueViaPutAll() {
|
|
Builder<String, Integer> builder = new Builder<>();
|
|
try {
|
|
builder.putAll(Collections.<String, Integer>singletonMap("one", null));
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
}
|
|
|
|
public void testPuttingTheSameKeyTwiceThrowsOnBuild() {
|
|
Builder<String, Integer> builder =
|
|
new Builder<String, Integer>()
|
|
.put("one", 1)
|
|
.put("one", 1); // throwing on this line would be even better
|
|
|
|
try {
|
|
builder.build();
|
|
fail();
|
|
} catch (IllegalArgumentException expected) {
|
|
}
|
|
}
|
|
|
|
public void testOf() {
|
|
assertMapEquals(ImmutableMap.of("one", 1), "one", 1);
|
|
assertMapEquals(ImmutableMap.of("one", 1, "two", 2), "one", 1, "two", 2);
|
|
assertMapEquals(
|
|
ImmutableMap.of("one", 1, "two", 2, "three", 3), "one", 1, "two", 2, "three", 3);
|
|
assertMapEquals(
|
|
ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4),
|
|
"one",
|
|
1,
|
|
"two",
|
|
2,
|
|
"three",
|
|
3,
|
|
"four",
|
|
4);
|
|
assertMapEquals(
|
|
ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4, "five", 5),
|
|
"one",
|
|
1,
|
|
"two",
|
|
2,
|
|
"three",
|
|
3,
|
|
"four",
|
|
4,
|
|
"five",
|
|
5);
|
|
assertMapEquals(
|
|
ImmutableMap.of(
|
|
"one", 1,
|
|
"two", 2,
|
|
"three", 3,
|
|
"four", 4,
|
|
"five", 5,
|
|
"six", 6),
|
|
"one",
|
|
1,
|
|
"two",
|
|
2,
|
|
"three",
|
|
3,
|
|
"four",
|
|
4,
|
|
"five",
|
|
5,
|
|
"six",
|
|
6);
|
|
assertMapEquals(
|
|
ImmutableMap.of(
|
|
"one", 1,
|
|
"two", 2,
|
|
"three", 3,
|
|
"four", 4,
|
|
"five", 5,
|
|
"six", 6,
|
|
"seven", 7),
|
|
"one",
|
|
1,
|
|
"two",
|
|
2,
|
|
"three",
|
|
3,
|
|
"four",
|
|
4,
|
|
"five",
|
|
5,
|
|
"six",
|
|
6,
|
|
"seven",
|
|
7);
|
|
assertMapEquals(
|
|
ImmutableMap.of(
|
|
"one", 1,
|
|
"two", 2,
|
|
"three", 3,
|
|
"four", 4,
|
|
"five", 5,
|
|
"six", 6,
|
|
"seven", 7,
|
|
"eight", 8),
|
|
"one",
|
|
1,
|
|
"two",
|
|
2,
|
|
"three",
|
|
3,
|
|
"four",
|
|
4,
|
|
"five",
|
|
5,
|
|
"six",
|
|
6,
|
|
"seven",
|
|
7,
|
|
"eight",
|
|
8);
|
|
assertMapEquals(
|
|
ImmutableMap.of(
|
|
"one", 1,
|
|
"two", 2,
|
|
"three", 3,
|
|
"four", 4,
|
|
"five", 5,
|
|
"six", 6,
|
|
"seven", 7,
|
|
"eight", 8,
|
|
"nine", 9),
|
|
"one",
|
|
1,
|
|
"two",
|
|
2,
|
|
"three",
|
|
3,
|
|
"four",
|
|
4,
|
|
"five",
|
|
5,
|
|
"six",
|
|
6,
|
|
"seven",
|
|
7,
|
|
"eight",
|
|
8,
|
|
"nine",
|
|
9);
|
|
assertMapEquals(
|
|
ImmutableMap.of(
|
|
"one", 1,
|
|
"two", 2,
|
|
"three", 3,
|
|
"four", 4,
|
|
"five", 5,
|
|
"six", 6,
|
|
"seven", 7,
|
|
"eight", 8,
|
|
"nine", 9,
|
|
"ten", 10),
|
|
"one",
|
|
1,
|
|
"two",
|
|
2,
|
|
"three",
|
|
3,
|
|
"four",
|
|
4,
|
|
"five",
|
|
5,
|
|
"six",
|
|
6,
|
|
"seven",
|
|
7,
|
|
"eight",
|
|
8,
|
|
"nine",
|
|
9,
|
|
"ten",
|
|
10);
|
|
}
|
|
|
|
public void testOfNullKey() {
|
|
try {
|
|
ImmutableMap.of(null, 1);
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
|
|
try {
|
|
ImmutableMap.of("one", 1, null, 2);
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
}
|
|
|
|
public void testOfNullValue() {
|
|
try {
|
|
ImmutableMap.of("one", null);
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
|
|
try {
|
|
ImmutableMap.of("one", 1, "two", null);
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
}
|
|
|
|
public void testOfWithDuplicateKey() {
|
|
try {
|
|
ImmutableMap.of("one", 1, "one", 1);
|
|
fail();
|
|
} catch (IllegalArgumentException expected) {
|
|
}
|
|
}
|
|
|
|
public void testCopyOfEmptyMap() {
|
|
ImmutableMap<String, Integer> copy =
|
|
ImmutableMap.copyOf(Collections.<String, Integer>emptyMap());
|
|
assertEquals(Collections.<String, Integer>emptyMap(), copy);
|
|
assertSame(copy, ImmutableMap.copyOf(copy));
|
|
}
|
|
|
|
public void testCopyOfSingletonMap() {
|
|
ImmutableMap<String, Integer> copy = ImmutableMap.copyOf(Collections.singletonMap("one", 1));
|
|
assertMapEquals(copy, "one", 1);
|
|
assertSame(copy, ImmutableMap.copyOf(copy));
|
|
}
|
|
|
|
public void testCopyOf() {
|
|
Map<String, Integer> original = new LinkedHashMap<>();
|
|
original.put("one", 1);
|
|
original.put("two", 2);
|
|
original.put("three", 3);
|
|
|
|
ImmutableMap<String, Integer> copy = ImmutableMap.copyOf(original);
|
|
assertMapEquals(copy, "one", 1, "two", 2, "three", 3);
|
|
assertSame(copy, ImmutableMap.copyOf(copy));
|
|
}
|
|
|
|
public void testToImmutableMap() {
|
|
Collector<Entry<String, Integer>, ?, ImmutableMap<String, Integer>> collector =
|
|
ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue);
|
|
Equivalence<ImmutableMap<String, Integer>> equivalence =
|
|
Equivalence.equals()
|
|
.<Entry<String, Integer>>pairwise()
|
|
.onResultOf(ImmutableMap::entrySet);
|
|
CollectorTester.of(collector, equivalence)
|
|
.expectCollects(
|
|
ImmutableMap.of("one", 1, "two", 2, "three", 3),
|
|
mapEntry("one", 1),
|
|
mapEntry("two", 2),
|
|
mapEntry("three", 3));
|
|
}
|
|
|
|
public void testToImmutableMap_exceptionOnDuplicateKey() {
|
|
Collector<Entry<String, Integer>, ?, ImmutableMap<String, Integer>> collector =
|
|
ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue);
|
|
try {
|
|
Stream.of(mapEntry("one", 1), mapEntry("one", 11)).collect(collector);
|
|
fail("Expected IllegalArgumentException");
|
|
} catch (IllegalArgumentException expected) {
|
|
}
|
|
}
|
|
|
|
public void testToImmutableMapMerging() {
|
|
Collector<Entry<String, Integer>, ?, ImmutableMap<String, Integer>> collector =
|
|
ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue, Integer::sum);
|
|
Equivalence<ImmutableMap<String, Integer>> equivalence =
|
|
Equivalence.equals()
|
|
.<Entry<String, Integer>>pairwise()
|
|
.onResultOf(ImmutableMap::entrySet);
|
|
CollectorTester.of(collector, equivalence)
|
|
.expectCollects(
|
|
ImmutableMap.of("one", 1, "two", 4, "three", 3),
|
|
mapEntry("one", 1),
|
|
mapEntry("two", 2),
|
|
mapEntry("three", 3),
|
|
mapEntry("two", 2));
|
|
}
|
|
}
|
|
|
|
public void testNullGet() {
|
|
ImmutableMap<String, Integer> map = ImmutableMap.of("one", 1);
|
|
assertNull(map.get(null));
|
|
}
|
|
|
|
public void testAsMultimap() {
|
|
ImmutableMap<String, Integer> map =
|
|
ImmutableMap.of("one", 1, "won", 1, "two", 2, "too", 2, "three", 3);
|
|
ImmutableSetMultimap<String, Integer> expected =
|
|
ImmutableSetMultimap.of("one", 1, "won", 1, "two", 2, "too", 2, "three", 3);
|
|
assertEquals(expected, map.asMultimap());
|
|
}
|
|
|
|
public void testAsMultimapWhenEmpty() {
|
|
ImmutableMap<String, Integer> map = ImmutableMap.of();
|
|
ImmutableSetMultimap<String, Integer> expected = ImmutableSetMultimap.of();
|
|
assertEquals(expected, map.asMultimap());
|
|
}
|
|
|
|
public void testAsMultimapCaches() {
|
|
ImmutableMap<String, Integer> map = ImmutableMap.of("one", 1);
|
|
ImmutableSetMultimap<String, Integer> multimap1 = map.asMultimap();
|
|
ImmutableSetMultimap<String, Integer> multimap2 = map.asMultimap();
|
|
assertEquals(1, multimap1.asMap().size());
|
|
assertSame(multimap1, multimap2);
|
|
}
|
|
|
|
@GwtIncompatible // NullPointerTester
|
|
public void testNullPointers() {
|
|
NullPointerTester tester = new NullPointerTester();
|
|
tester.testAllPublicStaticMethods(ImmutableMap.class);
|
|
tester.testAllPublicInstanceMethods(new ImmutableMap.Builder<Object, Object>());
|
|
tester.testAllPublicInstanceMethods(ImmutableMap.of());
|
|
tester.testAllPublicInstanceMethods(ImmutableMap.of("one", 1));
|
|
tester.testAllPublicInstanceMethods(ImmutableMap.of("one", 1, "two", 2, "three", 3));
|
|
}
|
|
|
|
private static <K, V> void assertMapEquals(Map<K, V> map, Object... alternatingKeysAndValues) {
|
|
assertEquals(map.size(), alternatingKeysAndValues.length / 2);
|
|
int i = 0;
|
|
for (Entry<K, V> entry : map.entrySet()) {
|
|
assertEquals(alternatingKeysAndValues[i++], entry.getKey());
|
|
assertEquals(alternatingKeysAndValues[i++], entry.getValue());
|
|
}
|
|
}
|
|
|
|
private static class IntHolder implements Serializable {
|
|
public int value;
|
|
|
|
public IntHolder(int value) {
|
|
this.value = value;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
return (o instanceof IntHolder) && ((IntHolder) o).value == value;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return value;
|
|
}
|
|
|
|
private static final long serialVersionUID = 5;
|
|
}
|
|
|
|
public void testMutableValues() {
|
|
IntHolder holderA = new IntHolder(1);
|
|
IntHolder holderB = new IntHolder(2);
|
|
Map<String, IntHolder> map = ImmutableMap.of("a", holderA, "b", holderB);
|
|
holderA.value = 3;
|
|
assertTrue(map.entrySet().contains(Maps.immutableEntry("a", new IntHolder(3))));
|
|
Map<String, Integer> intMap = ImmutableMap.of("a", 3, "b", 2);
|
|
assertEquals(intMap.hashCode(), map.entrySet().hashCode());
|
|
assertEquals(intMap.hashCode(), map.hashCode());
|
|
}
|
|
|
|
public void testCopyOfEnumMap() {
|
|
EnumMap<AnEnum, String> map = new EnumMap<>(AnEnum.class);
|
|
map.put(AnEnum.B, "foo");
|
|
map.put(AnEnum.C, "bar");
|
|
assertTrue(ImmutableMap.copyOf(map) instanceof ImmutableEnumMap);
|
|
}
|
|
|
|
@GwtIncompatible // SerializableTester
|
|
public void testViewSerialization() {
|
|
Map<String, Integer> map = ImmutableMap.of("one", 1, "two", 2, "three", 3);
|
|
LenientSerializableTester.reserializeAndAssertLenient(map.entrySet());
|
|
LenientSerializableTester.reserializeAndAssertLenient(map.keySet());
|
|
|
|
Collection<Integer> reserializedValues = reserialize(map.values());
|
|
assertEquals(Lists.newArrayList(map.values()), Lists.newArrayList(reserializedValues));
|
|
assertTrue(reserializedValues instanceof ImmutableCollection);
|
|
}
|
|
|
|
@GwtIncompatible // SerializableTester
|
|
public void testKeySetIsSerializable_regularImmutableMap() {
|
|
class NonSerializableClass {}
|
|
|
|
Map<String, NonSerializableClass> map =
|
|
RegularImmutableMap.fromEntries(ImmutableMap.entryOf("one", new NonSerializableClass()));
|
|
Set<String> set = map.keySet();
|
|
|
|
LenientSerializableTester.reserializeAndAssertLenient(set);
|
|
}
|
|
|
|
@GwtIncompatible // SerializableTester
|
|
public void testKeySetIsSerializable_jdkBackedImmutableMap() {
|
|
class NonSerializableClass {}
|
|
|
|
Entry<String, NonSerializableClass>[] entries =
|
|
arrayOf(ImmutableMap.entryOf("one", new NonSerializableClass()));
|
|
|
|
Map<String, NonSerializableClass> map = JdkBackedImmutableMap.create(1, entries);
|
|
Set<String> set = map.keySet();
|
|
|
|
LenientSerializableTester.reserializeAndAssertLenient(set);
|
|
}
|
|
|
|
@GwtIncompatible // SerializableTester
|
|
public void testValuesCollectionIsSerializable_regularImmutableMap() {
|
|
class NonSerializableClass {}
|
|
|
|
Map<NonSerializableClass, String> map =
|
|
RegularImmutableMap.fromEntries(ImmutableMap.entryOf(new NonSerializableClass(), "value"));
|
|
Collection<String> collection = map.values();
|
|
|
|
LenientSerializableTester.reserializeAndAssertElementsEqual(collection);
|
|
}
|
|
|
|
@GwtIncompatible // SerializableTester
|
|
public void testValuesCollectionIsSerializable_jdkBackedImmutableMap() {
|
|
class NonSerializableClass {}
|
|
|
|
Entry<NonSerializableClass, String>[] entries =
|
|
arrayOf(ImmutableMap.entryOf(new NonSerializableClass(), "value"));
|
|
|
|
Map<NonSerializableClass, String> map = JdkBackedImmutableMap.create(1, entries);
|
|
Collection<String> collection = map.values();
|
|
|
|
LenientSerializableTester.reserializeAndAssertElementsEqual(collection);
|
|
}
|
|
|
|
// TODO: Re-enable this test after moving to new serialization format in ImmutableMap.
|
|
@GwtIncompatible // SerializableTester
|
|
@SuppressWarnings("unchecked")
|
|
public void ignore_testSerializationNoDuplication_regularImmutableMap() throws Exception {
|
|
// Tests that searializing a map, its keySet, and values only writes the underlying data once.
|
|
|
|
Entry<Integer, Integer>[] entries = (Entry<Integer, Integer>[]) new Entry<?, ?>[1000];
|
|
for (int i = 0; i < 1000; i++) {
|
|
entries[i] = ImmutableMap.entryOf(i, i);
|
|
}
|
|
|
|
ImmutableMap<Integer, Integer> map = RegularImmutableMap.fromEntries(entries);
|
|
Set<Integer> keySet = map.keySet();
|
|
Collection<Integer> values = map.values();
|
|
|
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
|
ObjectOutputStream oos = new ObjectOutputStream(bytes);
|
|
oos.writeObject(map);
|
|
oos.flush();
|
|
|
|
int mapSize = bytes.size();
|
|
oos.writeObject(keySet);
|
|
oos.writeObject(values);
|
|
oos.close();
|
|
|
|
int finalSize = bytes.size();
|
|
|
|
assertThat(finalSize - mapSize).isLessThan(100);
|
|
}
|
|
|
|
// TODO: Re-enable this test after moving to new serialization format in ImmutableMap.
|
|
@GwtIncompatible // SerializableTester
|
|
@SuppressWarnings("unchecked")
|
|
public void ignore_testSerializationNoDuplication_jdkBackedImmutableMap() throws Exception {
|
|
// Tests that searializing a map, its keySet, and values only writes
|
|
// the underlying data once.
|
|
|
|
Entry<Integer, Integer>[] entries = (Entry<Integer, Integer>[]) new Entry<?, ?>[1000];
|
|
for (int i = 0; i < 1000; i++) {
|
|
entries[i] = ImmutableMap.entryOf(i, i);
|
|
}
|
|
|
|
ImmutableMap<Integer, Integer> map = JdkBackedImmutableMap.create(entries.length, entries);
|
|
Set<Integer> keySet = map.keySet();
|
|
Collection<Integer> values = map.values();
|
|
|
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
|
ObjectOutputStream oos = new ObjectOutputStream(bytes);
|
|
oos.writeObject(map);
|
|
oos.flush();
|
|
|
|
int mapSize = bytes.size();
|
|
oos.writeObject(keySet);
|
|
oos.writeObject(values);
|
|
oos.close();
|
|
|
|
int finalSize = bytes.size();
|
|
|
|
assertThat(finalSize - mapSize).isLessThan(100);
|
|
}
|
|
|
|
private static <T> T[] arrayOf(T... objs) {
|
|
return objs;
|
|
}
|
|
|
|
@GwtIncompatible("assumptions about splitting")
|
|
public void testKeySetSplittable() {
|
|
ImmutableMap<Integer, Integer> map =
|
|
ImmutableMap.<Integer, Integer>builder()
|
|
.put(1, 1)
|
|
.put(2, 2)
|
|
.put(3, 3)
|
|
.put(4, 4)
|
|
.put(5, 5)
|
|
.put(6, 6)
|
|
.build();
|
|
assertNotNull(map.keySet().spliterator().trySplit());
|
|
}
|
|
|
|
public void testEquals() {
|
|
new EqualsTester()
|
|
.addEqualityGroup(
|
|
ImmutableMap.of(), ImmutableMap.builder().build(), ImmutableMap.ofEntries(), map())
|
|
.addEqualityGroup(
|
|
ImmutableMap.of(1, 1),
|
|
ImmutableMap.builder().put(1, 1).build(),
|
|
ImmutableMap.ofEntries(entry(1, 1)),
|
|
map(1, 1))
|
|
.addEqualityGroup(
|
|
ImmutableMap.of(1, 1, 2, 2),
|
|
ImmutableMap.builder().put(1, 1).put(2, 2).build(),
|
|
ImmutableMap.ofEntries(entry(1, 1), entry(2, 2)),
|
|
map(1, 1, 2, 2))
|
|
.addEqualityGroup(
|
|
ImmutableMap.of(1, 1, 2, 2, 3, 3),
|
|
ImmutableMap.builder().put(1, 1).put(2, 2).put(3, 3).build(),
|
|
ImmutableMap.ofEntries(entry(1, 1), entry(2, 2), entry(3, 3)),
|
|
map(1, 1, 2, 2, 3, 3))
|
|
.addEqualityGroup(
|
|
ImmutableMap.of(1, 4, 2, 2, 3, 3),
|
|
ImmutableMap.builder().put(1, 4).put(2, 2).put(3, 3).build(),
|
|
ImmutableMap.ofEntries(entry(1, 4), entry(2, 2), entry(3, 3)),
|
|
map(1, 4, 2, 2, 3, 3))
|
|
.addEqualityGroup(
|
|
ImmutableMap.of(1, 1, 2, 4, 3, 3),
|
|
ImmutableMap.builder().put(1, 1).put(2, 4).put(3, 3).build(),
|
|
ImmutableMap.ofEntries(entry(1, 1), entry(2, 4), entry(3, 3)),
|
|
map(1, 1, 2, 4, 3, 3))
|
|
.addEqualityGroup(
|
|
ImmutableMap.of(1, 1, 2, 2, 3, 4),
|
|
ImmutableMap.builder().put(1, 1).put(2, 2).put(3, 4).build(),
|
|
ImmutableMap.ofEntries(entry(1, 1), entry(2, 2), entry(3, 4)),
|
|
map(1, 1, 2, 2, 3, 4))
|
|
.addEqualityGroup(
|
|
ImmutableMap.of(1, 2, 2, 3, 3, 1),
|
|
ImmutableMap.builder().put(1, 2).put(2, 3).put(3, 1).build(),
|
|
ImmutableMap.ofEntries(entry(1, 2), entry(2, 3), entry(3, 1)),
|
|
map(1, 2, 2, 3, 3, 1))
|
|
.addEqualityGroup(
|
|
ImmutableMap.of(1, 1, 2, 2, 3, 3, 4, 4),
|
|
ImmutableMap.builder().put(1, 1).put(2, 2).put(3, 3).put(4, 4).build(),
|
|
ImmutableMap.ofEntries(entry(1, 1), entry(2, 2), entry(3, 3), entry(4, 4)),
|
|
map(1, 1, 2, 2, 3, 3, 4, 4))
|
|
.addEqualityGroup(
|
|
ImmutableMap.of(1, 1, 2, 2, 3, 3, 4, 4, 5, 5),
|
|
ImmutableMap.builder().put(1, 1).put(2, 2).put(3, 3).put(4, 4).put(5, 5).build(),
|
|
ImmutableMap.ofEntries(entry(1, 1), entry(2, 2), entry(3, 3), entry(4, 4), entry(5, 5)),
|
|
map(1, 1, 2, 2, 3, 3, 4, 4, 5, 5))
|
|
.testEquals();
|
|
}
|
|
|
|
public void testOfEntriesNull() {
|
|
Entry<Integer, Integer> nullKey = entry(null, 23);
|
|
try {
|
|
ImmutableMap.ofEntries(nullKey);
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
Entry<Integer, Integer> nullValue = entry(23, null);
|
|
try {
|
|
ImmutableMap.ofEntries(nullValue);
|
|
fail();
|
|
} catch (NullPointerException expected) {
|
|
}
|
|
}
|
|
|
|
private static <T> Map<T, T> map(T... keysAndValues) {
|
|
assertThat(keysAndValues.length % 2).isEqualTo(0);
|
|
LinkedHashMap<T, T> map = new LinkedHashMap<>();
|
|
for (int i = 0; i < keysAndValues.length; i += 2) {
|
|
T key = keysAndValues[i];
|
|
T value = keysAndValues[i + 1];
|
|
T old = map.put(key, value);
|
|
assertWithMessage("Key %s set to %s and %s", key, value, old).that(old).isNull();
|
|
}
|
|
return map;
|
|
}
|
|
|
|
private static <T> Entry<T, T> entry(T key, T value) {
|
|
return new AbstractMap.SimpleImmutableEntry<>(key, value);
|
|
}
|
|
|
|
public void testCopyOfMutableEntryList() {
|
|
List<Entry<String, String>> entryList =
|
|
Arrays.asList(
|
|
new AbstractMap.SimpleEntry<>("a", "1"), new AbstractMap.SimpleEntry<>("b", "2"));
|
|
ImmutableMap<String, String> map = ImmutableMap.copyOf(entryList);
|
|
assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
|
|
entryList.get(0).setValue("3");
|
|
assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
|
|
}
|
|
|
|
public void testBuilderPutAllEntryList() {
|
|
List<Entry<String, String>> entryList =
|
|
Arrays.asList(
|
|
new AbstractMap.SimpleEntry<>("a", "1"), new AbstractMap.SimpleEntry<>("b", "2"));
|
|
ImmutableMap<String, String> map =
|
|
ImmutableMap.<String, String>builder().putAll(entryList).build();
|
|
assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
|
|
entryList.get(0).setValue("3");
|
|
assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
|
|
}
|
|
|
|
public void testBuilderPutAllEntryListJdkBacked() {
|
|
List<Entry<String, String>> entryList =
|
|
Arrays.asList(
|
|
new AbstractMap.SimpleEntry<>("a", "1"), new AbstractMap.SimpleEntry<>("b", "2"));
|
|
ImmutableMap<String, String> map =
|
|
ImmutableMap.<String, String>builder().putAll(entryList).buildJdkBacked();
|
|
assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
|
|
entryList.get(0).setValue("3");
|
|
assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
|
|
}
|
|
|
|
public static class FloodingTest extends AbstractHashFloodingTest<Map<Object, Object>> {
|
|
public FloodingTest() {
|
|
super(
|
|
Arrays.asList(ConstructionPathway.values()),
|
|
n -> n * Math.log(n),
|
|
ImmutableList.of(QueryOp.MAP_GET));
|
|
}
|
|
|
|
/** All the ways to create an ImmutableMap. */
|
|
enum ConstructionPathway implements Construction<Map<Object, Object>> {
|
|
COPY_OF_MAP {
|
|
@Override
|
|
public Map<Object, Object> create(List<?> keys) {
|
|
Map<Object, Object> sourceMap = new LinkedHashMap<>();
|
|
for (Object k : keys) {
|
|
if (sourceMap.put(k, "dummy value") != null) {
|
|
throw new UnsupportedOperationException("duplicate key");
|
|
}
|
|
}
|
|
return ImmutableMap.copyOf(sourceMap);
|
|
}
|
|
},
|
|
COPY_OF_ENTRIES {
|
|
@Override
|
|
public Map<Object, Object> create(List<?> keys) {
|
|
return ImmutableMap.copyOf(
|
|
Lists.transform(keys, k -> Maps.immutableEntry(k, "dummy value")));
|
|
}
|
|
},
|
|
BUILDER_PUT_ONE_BY_ONE {
|
|
@Override
|
|
public Map<Object, Object> create(List<?> keys) {
|
|
ImmutableMap.Builder<Object, Object> builder = ImmutableMap.builder();
|
|
for (Object k : keys) {
|
|
builder.put(k, "dummy value");
|
|
}
|
|
return builder.build();
|
|
}
|
|
},
|
|
BUILDER_PUT_ENTRIES_ONE_BY_ONE {
|
|
@Override
|
|
public Map<Object, Object> create(List<?> keys) {
|
|
ImmutableMap.Builder<Object, Object> builder = ImmutableMap.builder();
|
|
for (Object k : keys) {
|
|
builder.put(Maps.immutableEntry(k, "dummy value"));
|
|
}
|
|
return builder.build();
|
|
}
|
|
},
|
|
BUILDER_PUT_ALL_MAP {
|
|
@Override
|
|
public Map<Object, Object> create(List<?> keys) {
|
|
Map<Object, Object> sourceMap = new LinkedHashMap<>();
|
|
for (Object k : keys) {
|
|
if (sourceMap.put(k, "dummy value") != null) {
|
|
throw new UnsupportedOperationException("duplicate key");
|
|
}
|
|
}
|
|
return ImmutableMap.builder().putAll(sourceMap).build();
|
|
}
|
|
},
|
|
BUILDER_PUT_ALL_ENTRIES {
|
|
@Override
|
|
public Map<Object, Object> create(List<?> keys) {
|
|
return ImmutableMap.builder()
|
|
.putAll(Lists.transform(keys, k -> Maps.immutableEntry(k, "dummy value")))
|
|
.build();
|
|
}
|
|
},
|
|
FORCE_JDK {
|
|
@Override
|
|
public Map<Object, Object> create(List<?> keys) {
|
|
ImmutableMap.Builder<Object, Object> builder = ImmutableMap.builder();
|
|
for (Object k : keys) {
|
|
builder.put(k, "dummy value");
|
|
}
|
|
return builder.buildJdkBacked();
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|