Java Language
Mapy
Szukaj…
Wprowadzenie
Interfejs java.util.Map reprezentuje odwzorowanie między kluczami i ich wartościami. Mapa nie może zawierać zduplikowanych kluczy; a każdy klucz może być przypisany maksymalnie do jednej wartości.
Ponieważ Map
jest interfejsem, musisz utworzyć konkretną implementację tego interfejsu, aby go użyć; istnieje kilka implementacji Map
, a najczęściej używane są java.util.HashMap
i java.util.TreeMap
Uwagi
Mapa to obiekt przechowujący klucze z przypisaną wartością dla każdego klucza. Klucz i jego wartość są czasami nazywane parą klucz / wartość lub wpisem . Mapy zazwyczaj zapewniają następujące funkcje:
- Dane są przechowywane na mapie w parach klucz / wartość.
- Mapa może zawierać tylko jeden wpis dla określonego klucza. Jeśli mapa zawiera wpis z określonym kluczem, a Ty próbujesz zapisać drugi wpis z tym samym kluczem, wówczas drugi wpis zastąpi pierwszy. Innymi słowy, zmieni to wartość związaną z kluczem.
- Mapy zapewniają szybkie operacje sprawdzania, czy klucz istnieje na mapie, pobierania wartości powiązanej z kluczem i usuwania pary klucz / wartość.
Najczęściej stosowaną implementacją map jest HashMap . Działa dobrze z kluczami, które są ciągami lub cyframi.
Zwykłe mapy, takie jak HashMap, są nieuporządkowane. Iteracja parami klucz / wartość może zwracać pojedyncze wpisy w dowolnej kolejności. Jeśli potrzebujesz iterować wpisy mapy w kontrolowany sposób, powinieneś spojrzeć na następujące kwestie:
Posortowane mapy, takie jak TreeMap, będą iterowały klucze w ich naturalnej kolejności (lub w kolejności, którą możesz określić, podając komparator ). Na przykład, posortowana mapa wykorzystująca liczby jako klucze powinna się powtarzać po wpisach w kolejności numerycznej.
LinkedHashMap pozwala na iterację wpisów w tej samej kolejności, w jakiej zostały wstawione do mapy, lub w kolejności ostatnio otwieranych.
Dodaj element
- Dodanie
Map<Integer, String> map = new HashMap<>();
map.put(1, "First element.");
System.out.println(map.get(1));
Wyjście: First element.
- Nadpisanie
Map<Integer, String> map = new HashMap<>();
map.put(1, "First element.");
map.put(1, "New element.");
System.out.println(map.get(1));
Wyjście: New element.
Przykładem jest HashMap
. Można również zastosować inne implementacje, które implementują interfejs Map
.
Dodaj wiele elementów
Możemy użyć V put(K key,V value)
:
Kojarzy określoną wartość z określonym kluczem na tej mapie (operacja opcjonalna). Jeśli mapa poprzednio zawierała mapowanie klucza, stara wartość zostanie zastąpiona określoną wartością.
String currentVal;
Map<Integer, String> map = new TreeMap<>();
currentVal = map.put(1, "First element.");
System.out.println(currentVal);// Will print null
currentVal = map.put(2, "Second element.");
System.out.println(currentVal); // Will print null yet again
currentVal = map.put(2, "This will replace 'Second element'");
System.out.println(currentVal); // will print Second element.
System.out.println(map.size()); // Will print 2 as key having
// value 2 was replaced.
Map<Integer, String> map2 = new HashMap<>();
map2.put(2, "Element 2");
map2.put(3, "Element 3");
map.putAll(map2);
System.out.println(map.size());
Wynik:
3
Aby dodać wiele przedmiotów, możesz użyć wewnętrznych klas takich jak to:
Map<Integer, String> map = new HashMap<>() {{
// This is now an anonymous inner class with an unnamed instance constructor
put(5, "high");
put(4, "low");
put(1, "too slow");
}};
Należy pamiętać, że utworzenie anonimowej klasy wewnętrznej nie zawsze jest wydajne i może prowadzić do wycieków pamięci, więc jeśli to możliwe, należy zamiast tego użyć bloku inicjalizującego:
static Map<Integer, String> map = new HashMap<>();
static {
// Now no inner classes are created so we can avoid memory leaks
put(5, "high");
put(4, "low");
put(1, "too slow");
}
Powyższy przykład powoduje, że mapa staje się statyczna. Może być również stosowany w kontekście non-statycznego poprzez usunięcie wszystkich wystąpień static
.
Poza tym większość implementacji obsługuje putAll
, które mogą dodawać wszystkie wpisy z jednej mapy do drugiej w następujący sposób:
another.putAll(one);
Korzystanie z domyślnych metod mapowania z Java 8
Przykłady użycia metod domyślnych wprowadzonych w Javie 8 w interfejsie mapy
- Korzystanie z getOrDefault
Zwraca wartość zamapowaną na klucz lub, jeśli klucz nie jest obecny, zwraca wartość domyślną
Map<Integer, String> map = new HashMap<>();
map.put(1, "First element");
map.get(1); // => First element
map.get(2); // => null
map.getOrDefault(2, "Default element"); // => Default element
- Korzystanie z forEach
Pozwala wykonać operację określoną w „akcji” na każdym Wpisie mapy
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.forEach((key, value) -> System.out.println("Key: "+key+ " :: Value: "+value));
// Key: 1 :: Value: one
// Key: 2 :: Value: two
// Key: 3 :: Value: three
- Korzystanie z replaceAll
Zastąpi nową wartością tylko wtedy, gdy klucz jest obecny
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.replaceAll((key,value)->value+10); //{john=30, paul=40, peter=50}
- Korzystanie z putIfAbsent
Para klucz-wartość jest dodawana do mapy, jeśli klucz nie jest obecny lub zmapowany na zero
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.putIfAbsent("kelly", 50); //{john=20, paul=30, peter=40, kelly=50}
Korzystanie z usuwania
Usuwa klucz tylko wtedy, gdy jest powiązany z podaną wartością
Map<String, Integer> map = new HashMap<String, Integer>(); map.put("john", 20); map.put("paul", 30); map.put("peter", 40); map.remove("peter",40); //{john=30, paul=40}
Za pomocą zamiany
Jeśli klucz jest obecny, wartość jest zastępowana nową wartością. Jeśli klucz nie jest obecny, nic nie robi.
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.replace("peter",50); //{john=20, paul=30, peter=50}
map.replace("jack",60); //{john=20, paul=30, peter=50}
- Korzystanie z computeIfAbsent
Ta metoda dodaje wpis na mapie. klucz jest określony w funkcji, a wartość jest wynikiem zastosowania funkcji mapowania
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.computeIfAbsent("kelly", k->map.get("john")+10); //{john=20, paul=30, peter=40, kelly=30}
map.computeIfAbsent("peter", k->map.get("john")+10); //{john=20, paul=30, peter=40, kelly=30} //peter already present
- Korzystanie z computeIfPresent
Ta metoda dodaje wpis lub modyfikuje istniejący wpis na mapie. Nie robi nic, jeśli nie ma wpisu z tym kluczem
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.computeIfPresent("kelly", (k,v)->v+10); //{john=20, paul=30, peter=40} //kelly not present
map.computeIfPresent("peter", (k,v)->v+10); //{john=20, paul=30, peter=50} // peter present, so increase the value
- Korzystanie z obliczeń
Ta metoda zastępuje wartość klucza nowo obliczoną wartością
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.compute("peter", (k,v)->v+50); //{john=20, paul=30, peter=90} //Increase the value
- Używanie scalania
Dodaje parę klucz-wartość do mapy, jeśli klucz nie jest obecny lub wartość klucza jest pusta Zastępuje wartość nowo obliczoną wartością, jeśli klucz jest obecny Klucz jest usuwany z mapy, jeśli nowa obliczona wartość jest zerowa
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
//Adds the key-value pair to the map, if key is not present or value for the key is null
map.merge("kelly", 50 , (k,v)->map.get("john")+10); // {john=20, paul=30, peter=40, kelly=50}
//Replaces the value with the newly computed value, if the key is present
map.merge("peter", 50 , (k,v)->map.get("john")+10); //{john=20, paul=30, peter=30, kelly=50}
//Key is removed from the map , if new value computed is null
map.merge("peter", 30 , (k,v)->map.get("nancy")); //{john=20, paul=30, kelly=50}
Wyczyść mapę
Map<Integer, String> map = new HashMap<>();
map.put(1, "First element.");
map.put(2, "Second element.");
map.put(3, "Third element.");
map.clear();
System.out.println(map.size()); // => 0
Iterowanie po zawartości mapy
Mapy udostępniają metody, które umożliwiają dostęp do kluczy, wartości lub par klucz-wartość mapy jako zbiorów. Możesz iterować po tych kolekcjach. Biorąc pod uwagę następującą mapę, na przykład:
Map<String, Integer> repMap = new HashMap<>();
repMap.put("Jon Skeet", 927_654);
repMap.put("BalusC", 708_826);
repMap.put("Darin Dimitrov", 715_567);
Iterowanie za pomocą klawiszy mapy:
for (String key : repMap.keySet()) {
System.out.println(key);
}
Wydruki:
Darin Dimitrov
Jon Skeet
BalusC
keySet()
udostępnia klucze mapy jako Set
. Set
jest używany, ponieważ klucze nie mogą zawierać zduplikowanych wartości. Iteracja po zestawie daje kolejno każdy klucz. HashMapy nie są zamawiane, więc w tym przykładzie klucze mogą być zwracane w dowolnej kolejności.
Iteracja po wartościach mapy:
for (Integer value : repMap.values()) {
System.out.println(value);
}
Wydruki:
715567
927654
708826
values()
zwraca wartości mapy jako Collection
. Iteracja kolekcji daje kolejno każdą wartość. Ponownie wartości mogą być zwracane w dowolnej kolejności.
Iteracja przez klucze i wartości razem
for (Map.Entry<String, Integer> entry : repMap.entrySet()) {
System.out.printf("%s = %d\n", entry.getKey(), entry.getValue());
}
Wydruki:
Darin Dimitrov = 715567
Jon Skeet = 927654
BalusC = 708826
entrySet()
zwraca kolekcję Map.Entry
obiektów. Map.Entry daje dostęp do klucza i wartości dla każdego wpisu.
Scalanie, łączenie i komponowanie Map
Użyj putAll
aby umieścić każdego członka jednej mapy w innym. Klucze już obecne na mapie zostaną zastąpione odpowiadającymi im wartościami.
Map<String, Integer> numbers = new HashMap<>();
numbers.put("One", 1)
numbers.put("Three", 3)
Map<String, Integer> other_numbers = new HashMap<>();
other_numbers.put("Two", 2)
other_numbers.put("Three", 4)
numbers.putAll(other_numbers)
Daje to następujące mapowanie numbers
:
"One" -> 1
"Two" -> 2
"Three" -> 4 //old value 3 was overwritten by new value 4
Jeśli chcesz łączyć wartości zamiast nadpisywać je, możesz użyć Map.merge
, dodanego w Javie 8, który używa podanej przez użytkownika funkcji BiFunction
do scalania wartości dla duplikatów kluczy. merge
działa na poszczególnych kluczach i wartościach, więc musisz użyć pętli lub Map.forEach
. Tutaj łączymy ciągi dla zduplikowanych kluczy:
for (Map.Entry<String, Integer> e : other_numbers.entrySet())
numbers.merge(e.getKey(), e.getValue(), Integer::sum);
//or instead of the above loop
other_numbers.forEach((k, v) -> numbers.merge(k, v, Integer::sum));
Jeśli chcesz wymusić ograniczenie, nie ma duplikatów kluczy, możesz użyć funkcji scalającej, która zgłasza błąd AssertionError
:
mapA.forEach((k, v) ->
mapB.merge(k, v, (v1, v2) ->
{throw new AssertionError("duplicate values for key: "+k);}));
Komponowanie mapy <X, Y> i mapy <Y, Z> w celu uzyskania mapy <X, Z>
Jeśli chcesz skomponować dwa mapowania, możesz to zrobić w następujący sposób
Map<String, Integer> map1 = new HashMap<String, Integer>();
map1.put("key1", 1);
map1.put("key2", 2);
map1.put("key3", 3);
Map<Integer, Double> map2 = new HashMap<Integer, Double>();
map2.put(1, 1.0);
map2.put(2, 2.0);
map2.put(3, 3.0);
Map<String, Double> map3 = new new HashMap<String, Double>();
map1.forEach((key,value)->map3.put(key,map2.get(value)));
Daje to następujące mapowanie
"key1" -> 1.0
"key2" -> 2.0
"key3" -> 3.0
Sprawdź, czy klucz istnieje
Map<String, String> num = new HashMap<>();
num.put("one", "first");
if (num.containsKey("one")) {
System.out.println(num.get("one")); // => first
}
Mapy mogą zawierać wartości zerowe
W przypadku map należy zachować ostrożność, aby nie pomylić „zawierającego klucza” z „posiadaniem wartości”. Na przykład HashMap
może zawierać null, co oznacza, że następujące zachowanie jest całkowicie normalne:
Map<String, String> map = new HashMap<>();
map.put("one", null);
if (map.containsKey("one")) {
System.out.println("This prints !"); // This line is reached
}
if (map.get("one") != null) {
System.out.println("This is never reached !"); // This line is never reached
}
Mówiąc bardziej formalnie, nie ma gwarancji, że map.contains(key) <=> map.get(key)!=null
Iterowanie wpisów na mapie w wydajny sposób
W tej sekcji podano kod i testy porównawcze dla dziesięciu unikalnych przykładowych implementacji, które iterują wpisy Map<Integer, Integer>
i generują sumę wartości Integer
. Wszystkie przykłady mają złożoność algorytmiczną Θ(n)
, jednak testy porównawcze są nadal przydatne do zapewnienia wglądu w to, które wdrożenia są bardziej wydajne w środowisku „rzeczywistym”.
Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, Integer> pair = it.next();
sum += pair.getKey() + pair.getValue();
}
for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
sum += pair.getKey() + pair.getValue();
}
- Implementacja przy użyciu
Map.forEach
(Java 8+)
map.forEach((k, v) -> sum[0] += k + v);
- Implementacja za pomocą
Map.keySet
zfor
for (Integer key : map.keySet()) {
sum += key + map.get(key);
}
- Implementacja za pomocą
Map.keySet
zIterator
Iterator<Integer> it = map.keySet().iterator();
while (it.hasNext()) {
Integer key = it.next();
sum += key + map.get(key);
}
for (Iterator<Map.Entry<Integer, Integer>> entries =
map.entrySet().iterator(); entries.hasNext(); ) {
Map.Entry<Integer, Integer> entry = entries.next();
sum += entry.getKey() + entry.getValue();
}
- Implementacja przy użyciu
Stream.forEach
(Java 8+)
map.entrySet().stream().forEach(e -> sum += e.getKey() + e.getValue());
- Implementacja przy użyciu
Stream.forEach
zeStream.parallel
(Java 8+)
map.entrySet()
.stream()
.parallel()
.forEach(e -> sum += e.getKey() + e.getValue());
- Implementacja przy użyciu
IterableMap
z kolekcji Apache
MapIterator<Integer, Integer> mit = iterableMap.mapIterator();
while (mit.hasNext()) {
sum += mit.next() + it.getValue();
}
- Implementacja przy użyciu
MutableMap
z kolekcji Eclipse
mutableMap.forEachKeyValue((key, value) -> {
sum += key + value;
});
Testy wydajności ( kod dostępny na Github )
Środowisko testowe: Windows 8.1 64-bit, Intel i7-4790 3,60 GHz, 16 GB
Średnia wydajność 10 prób (100 elementów) Najlepsza: 308 ± 21 ns / op
Benchmark Score Error Units test3_UsingForEachAndJava8 308 ± 21 ns/op test10_UsingEclipseMutableMap 309 ± 9 ns/op test1_UsingWhileAndMapEntry 380 ± 14 ns/op test6_UsingForAndIterator 387 ± 16 ns/op test2_UsingForEachAndMapEntry 391 ± 23 ns/op test7_UsingJava8StreamAPI 510 ± 14 ns/op test9_UsingApacheIterableMap 524 ± 8 ns/op test4_UsingKeySetAndForEach 816 ± 26 ns/op test5_UsingKeySetAndIterator 863 ± 25 ns/op test8_UsingJava8StreamAPIParallel 5552 ± 185 ns/op
Średnia wydajność 10 prób (10000 elementów) Najlepsza: 37,606 ± 0,790 μs / op
Benchmark Score Error Units test10_UsingEclipseMutableMap 37606 ± 790 ns/op test3_UsingForEachAndJava8 50368 ± 887 ns/op test6_UsingForAndIterator 50332 ± 507 ns/op test2_UsingForEachAndMapEntry 51406 ± 1032 ns/op test1_UsingWhileAndMapEntry 52538 ± 2431 ns/op test7_UsingJava8StreamAPI 54464 ± 712 ns/op test4_UsingKeySetAndForEach 79016 ± 25345 ns/op test5_UsingKeySetAndIterator 91105 ± 10220 ns/op test8_UsingJava8StreamAPIParallel 112511 ± 365 ns/op test9_UsingApacheIterableMap 125714 ± 1935 ns/op
Średnia wydajność 10 prób (100000 elementów) Najlepsza: 1184,767 ± 332,968 μs / op
Benchmark Score Error Units test1_UsingWhileAndMapEntry 1184.767 ± 332.968 μs/op test10_UsingEclipseMutableMap 1191.735 ± 304.273 μs/op test2_UsingForEachAndMapEntry 1205.815 ± 366.043 μs/op test6_UsingForAndIterator 1206.873 ± 367.272 μs/op test8_UsingJava8StreamAPIParallel 1485.895 ± 233.143 μs/op test5_UsingKeySetAndIterator 1540.281 ± 357.497 μs/op test4_UsingKeySetAndForEach 1593.342 ± 294.417 μs/op test3_UsingForEachAndJava8 1666.296 ± 126.443 μs/op test7_UsingJava8StreamAPI 1706.676 ± 436.867 μs/op test9_UsingApacheIterableMap 3289.866 ± 1445.564 μs/op
Porównanie wariantów wydajności w zależności od wielkości mapy
x: Size of Map
f(x): Benchmark Score (μs/op)
100 600 1100 1600 2100
---------------------------------------------------
10 | 0.333 1.631 2.752 5.937 8.024
3 | 0.309 1.971 4.147 8.147 10.473
6 | 0.372 2.190 4.470 8.322 10.531
1 | 0.405 2.237 4.616 8.645 10.707
Tests 2 | 0.376 2.267 4.809 8.403 10.910
f(x) 7 | 0.473 2.448 5.668 9.790 12.125
9 | 0.565 2.830 5.952 13.22 16.965
4 | 0.808 5.012 8.813 13.939 17.407
5 | 0.81 5.104 8.533 14.064 17.422
8 | 5.173 12.499 17.351 24.671 30.403
Użyj niestandardowego obiektu jako klucza
Przed użyciem własnego obiektu jako klucza musisz zastąpić metodę hashCode () i equals () swojego obiektu.
W prostym przypadku miałbyś coś takiego:
class MyKey {
private String name;
MyKey(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof MyKey) {
return this.name.equals(((MyKey)obj).name);
}
return false;
}
@Override
public int hashCode() {
return this.name.hashCode();
}
}
hashCode
zadecyduje, do którego segmentu mieszania należy klucz, a equals
zdecyduje, który obiekt w tym segmencie skrótów.
Bez tych metod odniesienie do twojego obiektu zostanie użyte do powyższego porównania, które nie będzie działać, chyba że użyjesz tego samego odwołania do obiektu za każdym razem.
Zastosowanie HashMap
HashMap to implementacja interfejsu mapy, który zapewnia strukturę danych do przechowywania danych w parach klucz-wartość.
1. Deklaracja HashMap
Map<KeyType, ValueType> myMap = new HashMap<KeyType, ValueType>();
KeyType i ValueType muszą być poprawnymi typami w Javie, takimi jak - String, Integer, Float lub dowolna niestandardowa klasa, taka jak Employee, Student itp.
Na przykład: Map<String,Integer> myMap = new HashMap<String,Integer>();
2. Wstawianie wartości do HashMap.
Aby wstawić wartość do HashMap, musimy wywołać metodę put
na obiekcie HashMap, przekazując klucz i wartość jako parametry.
myMap.put("key1", 1);
myMap.put("key2", 2);
Jeśli wywołasz metodę put z kluczem, który już istnieje na mapie, metoda zastąpi jej wartość i zwróci starą wartość.
3. Pobieranie wartości z HashMap.
Aby uzyskać wartość z HashMap, musisz wywołać metodę get
, przekazując klucz jako parametr.
myMap.get("key1"); //return 1 (class Integer)
Jeśli przekażesz klucz, który nie istnieje w HashMap, ta metoda zwróci null
4. Sprawdź, czy klucz znajduje się na mapie, czy nie.
myMap.containsKey(varKey);
5. Sprawdź, czy wartość znajduje się na mapie, czy nie.
myMap.containsValue(varValue);
Powyższe metody zwrócą wartość boolean
true lub false, jeśli klucz, wartość istnieje na mapie lub nie.
Tworzenie i inicjowanie map
Wprowadzenie
Maps
przechowują pary klucz / wartość, gdzie każdy klucz ma przypisaną wartość. Biorąc pod uwagę konkretny klucz, mapa może bardzo szybko wyszukać powiązaną wartość.
Maps
, znane również jako tablica asocjacyjna, to obiekt przechowujący dane w postaci kluczy i wartości. W Javie mapy są reprezentowane za pomocą interfejsu Map, który nie jest rozszerzeniem interfejsu kolekcji.
Sposób 1: -
/*J2SE < 5.0*/ Map map = new HashMap(); map.put("name", "A"); map.put("address", "Malviya-Nagar"); map.put("city", "Jaipur"); System.out.println(map);
Sposób 2: -
/*J2SE 5.0+ style (use of generics):*/ Map<String, Object> map = new HashMap<>(); map.put("name", "A"); map.put("address", "Malviya-Nagar"); map.put("city", "Jaipur"); System.out.println(map);
Sposób 3: -
Map<String, Object> map = new HashMap<String, Object>(){{ put("name", "A"); put("address", "Malviya-Nagar"); put("city", "Jaipur"); }}; System.out.println(map);
Sposób 4: -
Map<String, Object> map = new TreeMap<String, Object>(); map.put("name", "A"); map.put("address", "Malviya-Nagar"); map.put("city", "Jaipur"); System.out.println(map);
Sposób 5: -
//Java 8 final Map<String, String> map = Arrays.stream(new String[][] { { "name", "A" }, { "address", "Malviya-Nagar" }, { "city", "jaipur" }, }).collect(Collectors.toMap(m -> m[0], m -> m[1])); System.out.println(map);
Sposób 6: -
//This way for initial a map in outside the function final static Map<String, String> map; static { map = new HashMap<String, String>(); map.put("a", "b"); map.put("c", "d"); }
Sposób 7: - Stworzenie niezmiennej mapy pojedynczych kluczy i wartości.
//Immutable single key-value map Map<String, String> singletonMap = Collections.singletonMap("key", "value");
Pamiętaj, że modyfikacja takiej mapy jest niemożliwa .
Wszelkie próby modyfikacji mapy spowodują zgłoszenie wyjątku UnsupportedOperationException.
//Immutable single key-value pair Map<String, String> singletonMap = Collections.singletonMap("key", "value"); singletonMap.put("newKey", "newValue"); //will throw UnsupportedOperationException singletonMap.putAll(new HashMap<>()); //will throw UnsupportedOperationException singletonMap.remove("key"); //will throw UnsupportedOperationException singletonMap.replace("key", "value", "newValue"); //will throw UnsupportedOperationException //and etc