diff --git a/core-java-modules/core-java-collections-maps-2/README.md b/core-java-modules/core-java-collections-maps-2/README.md
new file mode 100644
index 0000000000..da9279b191
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/README.md
@@ -0,0 +1,16 @@
+## Java Collections Cookbooks and Examples
+
+This module contains articles about Map data structures in Java.
+
+### Relevant Articles:
+- [Map of Primitives in Java](https://www.baeldung.com/java-map-primitives)
+- [Copying a HashMap in Java](https://www.baeldung.com/java-copy-hashmap)
+- [A Guide to Java HashMap](https://www.baeldung.com/java-hashmap)
+- [Guide to WeakHashMap in Java](https://www.baeldung.com/java-weakhashmap)
+- [Map to String Conversion in Java](https://www.baeldung.com/java-map-to-string-conversion)
+- [Iterate over a Map in Java](https://www.baeldung.com/java-iterate-map)
+- [Merging Two Maps with Java 8](https://www.baeldung.com/java-merge-maps)
+- [Sort a HashMap in Java](https://www.baeldung.com/java-hashmap-sort)
+- [Finding the Highest Value in a Java Map](https://www.baeldung.com/java-find-map-max)
+- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
+- More articles: [[<-- prev]](/core-java-collections-maps) [[next -->]](/core-java-collections-maps-3)
diff --git a/core-java-modules/core-java-collections-maps-2/pom.xml b/core-java-modules/core-java-collections-maps-2/pom.xml
new file mode 100644
index 0000000000..a08a4ac072
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/pom.xml
@@ -0,0 +1,79 @@
+
+
+ 4.0.0
+ core-java-collections-maps-2
+ 0.1.0-SNAPSHOT
+ core-java-collections-maps-2
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../../parent-java
+
+
+
+
+ org.eclipse.collections
+ eclipse-collections
+ ${eclipse-collections.version}
+
+
+ net.sf.trove4j
+ trove4j
+ ${trove4j.version}
+
+
+ it.unimi.dsi
+ fastutil
+ ${fastutil.version}
+
+
+ colt
+ colt
+ ${colt.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+ one.util
+ streamex
+ ${streamex.version}
+
+
+ com.jayway.awaitility
+ awaitility
+ ${avaitility.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+
+
+ 0.6.5
+ 4.1
+ 1.7.0
+ 8.2.0
+ 3.0.2
+ 8.1.0
+ 1.2.0
+ 3.11.1
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/Product.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/Product.java
new file mode 100644
index 0000000000..5559895730
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/Product.java
@@ -0,0 +1,133 @@
+package com.baeldung.map;
+
+import java.util.*;
+
+public class Product {
+
+ private String name;
+ private String description;
+ private List tags;
+
+ public Product(String name, String description) {
+ this.name = name;
+ this.description = description;
+ this.tags = new ArrayList<>();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public List getTags() {
+ return tags;
+ }
+
+ public Product addTagsOfOtherProdcut(Product product) {
+ this.tags.addAll(product.getTags());
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Product product = (Product) o;
+ return Objects.equals(name, product.name) &&
+ Objects.equals(description, product.description);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, description);
+ }
+
+ public static void forEach() {
+
+ HashMap productsByName = new HashMap<>();
+ productsByName.forEach( (key, product)
+ -> System.out.println("Key: " + key + " Product:" + product.getDescription())
+ //do something with the key and value
+ );
+
+ //Prior to Java 8:
+ for(Map.Entry entry : productsByName.entrySet()) {
+ Product product = entry.getValue();
+ String key = entry.getKey();
+ //do something with the key and value
+ }
+ }
+
+ public static void getOrDefault() {
+
+ HashMap productsByName = new HashMap<>();
+ Product chocolate = new Product("chocolate", "something sweet");
+ Product defaultProduct = productsByName.getOrDefault("horse carriage", chocolate);
+ Product bike = productsByName.getOrDefault("E-Bike", chocolate);
+
+ //Prior to Java 8:
+ Product bike2 = productsByName.containsKey("E-Bike")
+ ? productsByName.get("E-Bike")
+ : chocolate;
+ Product defaultProduct2 = productsByName.containsKey("horse carriage")
+ ? productsByName.get("horse carriage")
+ : chocolate;
+ }
+
+ public static void putIfAbsent() {
+
+ HashMap productsByName = new HashMap<>();
+ Product chocolate = new Product("chocolate", "something sweet");
+ productsByName.putIfAbsent("E-Bike", chocolate);
+
+ //Prior to Java 8:
+ if(productsByName.containsKey("E-Bike")) {
+ productsByName.put("E-Bike", chocolate);
+ }
+ }
+
+ public static void merge() {
+
+ HashMap productsByName = new HashMap<>();
+ Product eBike2 = new Product("E-Bike", "A bike with a battery");
+ eBike2.getTags().add("sport");
+ productsByName.merge("E-Bike", eBike2, Product::addTagsOfOtherProdcut);
+
+ //Prior to Java 8:
+ if(productsByName.containsKey("E-Bike")) {
+ productsByName.get("E-Bike").addTagsOfOtherProdcut(eBike2);
+ } else {
+ productsByName.put("E-Bike", eBike2);
+ }
+ }
+
+ public static void compute() {
+
+ HashMap productsByName = new HashMap<>();
+ Product eBike2 = new Product("E-Bike", "A bike with a battery");
+
+ productsByName.compute("E-Bike", (k,v) -> {
+ if(v != null) {
+ return v.addTagsOfOtherProdcut(eBike2);
+ } else {
+ return eBike2;
+ }
+ });
+
+ //Prior to Java 8:
+ if(productsByName.containsKey("E-Bike")) {
+ productsByName.get("E-Bike").addTagsOfOtherProdcut(eBike2);
+ } else {
+ productsByName.put("E-Bike", eBike2);
+ }
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java
new file mode 100644
index 0000000000..d13be924ff
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java
@@ -0,0 +1,34 @@
+package com.baeldung.map.convert;
+
+import com.google.common.base.Joiner;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class MapToString {
+
+ public static String convertWithIteration(Map map) {
+ StringBuilder mapAsString = new StringBuilder("{");
+ for (Integer key : map.keySet()) {
+ mapAsString.append(key + "=" + map.get(key) + ", ");
+ }
+ mapAsString.delete(mapAsString.length()-2, mapAsString.length()).append("}");
+ return mapAsString.toString();
+ }
+
+ public static String convertWithStream(Map map) {
+ String mapAsString = map.keySet().stream()
+ .map(key -> key + "=" + map.get(key))
+ .collect(Collectors.joining(", ", "{", "}"));
+ return mapAsString;
+ }
+
+ public static String convertWithGuava(Map map) {
+ return Joiner.on(",").withKeyValueSeparator("=").join(map);
+ }
+
+ public static String convertWithApache(Map map) {
+ return StringUtils.join(map);
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java
new file mode 100644
index 0000000000..416ba4dd9a
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java
@@ -0,0 +1,21 @@
+package com.baeldung.map.convert;
+
+import com.google.common.base.Splitter;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class StringToMap {
+
+ public static Map convertWithStream(String mapAsString) {
+ Map map = Arrays.stream(mapAsString.split(","))
+ .map(entry -> entry.split("="))
+ .collect(Collectors.toMap(entry -> entry[0], entry -> entry[1]));
+ return map;
+ }
+
+ public static Map convertWithGuava(String mapAsString) {
+ return Splitter.on(',').withKeyValueSeparator('=').split(mapAsString);
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java
new file mode 100644
index 0000000000..cb18f3aa11
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java
@@ -0,0 +1,55 @@
+package com.baeldung.map.copyhashmap;
+
+import org.apache.commons.lang3.SerializationUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class CopyHashMap {
+
+ public static HashMap copyUsingConstructor(HashMap originalMap) {
+ return new HashMap(originalMap);
+ }
+
+ public static HashMap copyUsingClone(HashMap originalMap) {
+ return (HashMap) originalMap.clone();
+ }
+
+ public static HashMap copyUsingPut(HashMap originalMap) {
+ HashMap shallowCopy = new HashMap();
+ Set> entries = originalMap.entrySet();
+ for(Map.Entry mapEntry: entries) {
+ shallowCopy.put(mapEntry.getKey(), mapEntry.getValue());
+ }
+
+ return shallowCopy;
+ }
+
+ public static HashMap copyUsingPutAll(HashMap originalMap) {
+ HashMap shallowCopy = new HashMap();
+ shallowCopy.putAll(originalMap);
+
+ return shallowCopy;
+ }
+
+ public static HashMap copyUsingJava8Stream(HashMap originalMap) {
+ Set> entries = originalMap.entrySet();
+ HashMap shallowCopy = (HashMap) entries
+ .stream()
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+
+ return shallowCopy;
+ }
+
+ public static HashMap shallowCopy(HashMap originalMap) {
+ return (HashMap) originalMap.clone();
+ }
+
+ public static HashMap deepCopy(HashMap originalMap) {
+ return SerializationUtils.clone(originalMap);
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java
new file mode 100644
index 0000000000..4d63abcfd0
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java
@@ -0,0 +1,80 @@
+package com.baeldung.map.initialize;
+
+import java.util.AbstractMap;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class MapInitializer {
+
+ public static Map articleMapOne;
+ static {
+ articleMapOne = new HashMap<>();
+ articleMapOne.put("ar01", "Intro to Map");
+ articleMapOne.put("ar02", "Some article");
+ }
+
+ public static Map createSingletonMap() {
+ Map passwordMap = Collections.singletonMap("username1", "password1");
+ return passwordMap;
+
+ }
+
+ public Map createEmptyMap() {
+ Map emptyMap = Collections.emptyMap();
+ return emptyMap;
+ }
+
+ public Map createUsingDoubleBrace() {
+ Map doubleBraceMap = new HashMap() {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ {
+ put("key1", "value1");
+ put("key2", "value2");
+ }
+ };
+ return doubleBraceMap;
+ }
+
+ public Map createMapUsingStreamStringArray() {
+ Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, })
+ .collect(Collectors.toMap(data -> data[0], data -> data[1]));
+
+ return map;
+ }
+
+ public Map createMapUsingStreamObjectArray() {
+ Map map = Stream.of(new Object[][] { { "data1", 1 }, { "data2", 2 }, })
+ .collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));
+
+ return map;
+ }
+
+ public Map createMapUsingStreamSimpleEntry() {
+ Map map = Stream.of(new AbstractMap.SimpleEntry<>("idea", 1), new AbstractMap.SimpleEntry<>("mobile", 2))
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+
+ return map;
+ }
+
+ public Map createMapUsingStreamSimpleImmutableEntry() {
+ Map map = Stream.of(new AbstractMap.SimpleImmutableEntry<>("idea", 1), new AbstractMap.SimpleImmutableEntry<>("mobile", 2))
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+
+ return map;
+ }
+
+ public Map createImmutableMapWithStreams() {
+ Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, })
+ .collect(Collectors.collectingAndThen(Collectors.toMap(data -> data[0], data -> data[1]), Collections:: unmodifiableMap));
+ return map;
+
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java
new file mode 100644
index 0000000000..b0c32e1487
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java
@@ -0,0 +1,74 @@
+package com.baeldung.map.iteration;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+public class MapIteration {
+
+ public static void main(String[] args) {
+ MapIteration mapIteration = new MapIteration();
+ Map map = new HashMap<>();
+
+ map.put("One", 1);
+ map.put("Three", 3);
+ map.put("Two", 2);
+
+ System.out.println("Iterating Keys of Map Using KeySet");
+ mapIteration.iterateKeys(map);
+
+ System.out.println("Iterating Map Using Entry Set");
+ mapIteration.iterateUsingEntrySet(map);
+
+ System.out.println("Iterating Using Iterator and Map Entry");
+ mapIteration.iterateUsingIteratorAndEntry(map);
+
+ System.out.println("Iterating Using KeySet and For Each");
+ mapIteration.iterateUsingKeySetAndForeach(map);
+
+ System.out.println("Iterating Map Using Lambda Expression");
+ mapIteration.iterateUsingLambda(map);
+
+ System.out.println("Iterating Using Stream API");
+ mapIteration.iterateUsingStreamAPI(map);
+ }
+
+ public void iterateUsingEntrySet(Map map) {
+ for (Map.Entry entry : map.entrySet()) {
+ System.out.println(entry.getKey() + ":" + entry.getValue());
+ }
+ }
+
+ public void iterateUsingLambda(Map map) {
+ map.forEach((k, v) -> System.out.println((k + ":" + v)));
+ }
+
+ public void iterateUsingIteratorAndEntry(Map map) {
+ Iterator> iterator = map.entrySet()
+ .iterator();
+ while (iterator.hasNext()) {
+ Map.Entry pair = iterator.next();
+ System.out.println(pair.getKey() + ":" + pair.getValue());
+ }
+ }
+
+ public void iterateUsingKeySetAndForeach(Map map) {
+ for (String key : map.keySet()) {
+ System.out.println(key + ":" + map.get(key));
+ }
+ }
+
+ public void iterateUsingStreamAPI(Map map) {
+ map.entrySet()
+ .stream()
+ .forEach(e -> System.out.println(e.getKey() + ":" + e.getValue()));
+ }
+
+ public void iterateKeys(Map map) {
+ for (String key : map.keySet()) {
+ System.out.println(key);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java
new file mode 100644
index 0000000000..8c33c857ee
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java
@@ -0,0 +1,92 @@
+package com.baeldung.map.mapmax;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+public class MapMax {
+
+ public > V maxUsingIteration(Map map) {
+
+ Map.Entry maxEntry = null;
+
+ for (Map.Entry entry : map.entrySet()) {
+
+ if (maxEntry == null || entry.getValue()
+ .compareTo(maxEntry.getValue()) > 0) {
+ maxEntry = entry;
+ }
+ }
+
+ return maxEntry.getValue();
+ }
+
+ public > V maxUsingCollectionsMax(Map map) {
+
+ Entry maxEntry = Collections.max(map.entrySet(), new Comparator>() {
+ public int compare(Entry e1, Entry e2) {
+ return e1.getValue()
+ .compareTo(e2.getValue());
+ }
+ });
+
+ return maxEntry.getValue();
+ }
+
+ public > V maxUsingCollectionsMaxAndLambda(Map map) {
+
+ Entry maxEntry = Collections.max(map.entrySet(), (Entry e1, Entry e2) -> e1.getValue()
+ .compareTo(e2.getValue()));
+
+ return maxEntry.getValue();
+ }
+
+ public > V maxUsingCollectionsMaxAndMethodReference(Map map) {
+
+ Entry maxEntry = Collections.max(map.entrySet(), Comparator.comparing(Map.Entry::getValue));
+
+ return maxEntry.getValue();
+ }
+
+ public > V maxUsingStreamAndLambda(Map map) {
+
+ Optional> maxEntry = map.entrySet()
+ .stream()
+ .max((Entry e1, Entry e2) -> e1.getValue()
+ .compareTo(e2.getValue()));
+
+ return maxEntry.get()
+ .getValue();
+ }
+
+ public > V maxUsingStreamAndMethodReference(Map map) {
+
+ Optional> maxEntry = map.entrySet()
+ .stream()
+ .max(Comparator.comparing(Map.Entry::getValue));
+
+ return maxEntry.get()
+ .getValue();
+ }
+
+ public static void main(String[] args) {
+
+ Map map = new HashMap();
+
+ map.put(1, 3);
+ map.put(2, 4);
+ map.put(3, 5);
+ map.put(4, 6);
+ map.put(5, 7);
+
+ MapMax mapMax = new MapMax();
+
+ System.out.println(mapMax.maxUsingIteration(map));
+ System.out.println(mapMax.maxUsingCollectionsMax(map));
+ System.out.println(mapMax.maxUsingCollectionsMaxAndLambda(map));
+ System.out.println(mapMax.maxUsingCollectionsMaxAndMethodReference(map));
+ System.out.println(mapMax.maxUsingStreamAndLambda(map));
+ System.out.println(mapMax.maxUsingStreamAndMethodReference(map));
+
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java
new file mode 100644
index 0000000000..d7fb0d1a1d
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java
@@ -0,0 +1,60 @@
+package com.baeldung.map.mergemaps;
+
+public class Employee implements Comparable {
+
+ private Long id;
+ private String name;
+
+ public Employee(Long id, String name) {
+ this.name = name;
+ this.id = id;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Employee employee = (Employee) o;
+
+ if (!id.equals(employee.id)) return false;
+ return name.equals(employee.name);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id.hashCode();
+ result = 31 * result + name.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Employee{" +
+ "id=" + id +
+ ", name='" + name + '\'' +
+ '}';
+ }
+
+ @Override
+ public int compareTo(Employee employee) {
+ return (int)(this.id - employee.getId());
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java
new file mode 100644
index 0000000000..4f187bad90
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java
@@ -0,0 +1,105 @@
+package com.baeldung.map.mergemaps;
+
+import one.util.streamex.EntryStream;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class MergeMaps {
+
+ private static Map map1 = new HashMap<>();
+ private static Map map2 = new HashMap<>();
+
+ public static void main(String[] args) {
+
+ initialize();
+
+ mergeFunction();
+
+ streamConcat();
+
+ streamOf();
+
+ streamEx();
+
+ streamMerge();
+ }
+
+ private static void streamMerge() {
+
+ Map map3 = map2.entrySet()
+ .stream()
+ .collect(
+ Collectors.toMap(
+ Map.Entry::getKey,
+ Map.Entry::getValue,
+ (v1, v2) -> new Employee(v1.getId(), v2.getName()),
+ () -> new HashMap<>(map1)
+ )
+ );
+
+ System.out.println(map3);
+ }
+
+ private static void streamEx() {
+ Map map3 = EntryStream.of(map1)
+ .append(EntryStream.of(map2))
+ .toMap((e1, e2) -> e1);
+
+ System.out.println(map3);
+
+ }
+
+ private static void streamOf() {
+ Map map3 = Stream.of(map1, map2)
+ .flatMap(map -> map.entrySet().stream())
+ .collect(
+ Collectors.toMap(
+ Map.Entry::getKey,
+ Map.Entry::getValue,
+ (v1, v2) -> new Employee(v1.getId(), v2.getName())
+ )
+ );
+
+ map3.entrySet().forEach(System.out::println);
+ }
+
+ private static void streamConcat() {
+ Map result = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream()).collect(Collectors.toMap(
+ Map.Entry::getKey,
+ Map.Entry::getValue,
+ (value1, value2) -> new Employee(value2.getId(), value1.getName())
+ ));
+
+ result.entrySet().forEach(System.out::println);
+ }
+
+ private static void mergeFunction() {
+ Map map3 = new HashMap<>(map1);
+
+ map2.forEach(
+ (key, value) -> map3.merge(key, value, (v1, v2) ->
+ new Employee(v1.getId(), v2.getName()))
+ );
+
+ map3.entrySet().forEach(System.out::println);
+ }
+
+
+ private static void initialize() {
+ Employee employee1 = new Employee(1L, "Henry");
+ map1.put(employee1.getName(), employee1);
+ Employee employee2 = new Employee(22L, "Annie");
+ map1.put(employee2.getName(), employee2);
+ Employee employee3 = new Employee(8L, "John");
+ map1.put(employee3.getName(), employee3);
+
+ Employee employee4 = new Employee(2L, "George");
+ map2.put(employee4.getName(), employee4);
+ Employee employee5 = new Employee(3L, "Henry");
+ map2.put(employee5.getName(), employee5);
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java
new file mode 100644
index 0000000000..30bec12ccc
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java
@@ -0,0 +1,69 @@
+package com.baeldung.map.primitives;
+
+import cern.colt.map.AbstractIntDoubleMap;
+import cern.colt.map.OpenIntDoubleHashMap;
+import gnu.trove.map.TDoubleIntMap;
+import gnu.trove.map.hash.TDoubleIntHashMap;
+import it.unimi.dsi.fastutil.ints.Int2BooleanMap;
+import it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap;
+import it.unimi.dsi.fastutil.ints.Int2BooleanSortedMap;
+import it.unimi.dsi.fastutil.ints.Int2BooleanSortedMaps;
+import org.eclipse.collections.api.map.primitive.ImmutableIntIntMap;
+import org.eclipse.collections.api.map.primitive.MutableIntIntMap;
+import org.eclipse.collections.api.map.primitive.MutableObjectDoubleMap;
+import org.eclipse.collections.impl.factory.primitive.IntIntMaps;
+import org.eclipse.collections.impl.factory.primitive.ObjectDoubleMaps;
+
+public class PrimitiveMaps {
+
+ public static void main(String[] args) {
+
+ eclipseCollectionsMap();
+ troveMap();
+ coltMap();
+ fastutilMap();
+ }
+
+ private static void fastutilMap() {
+ Int2BooleanMap int2BooleanMap = new Int2BooleanOpenHashMap();
+ int2BooleanMap.put(1, true);
+ int2BooleanMap.put(7, false);
+ int2BooleanMap.put(4, true);
+
+ boolean value = int2BooleanMap.get(1);
+
+ Int2BooleanSortedMap int2BooleanSorted = Int2BooleanSortedMaps.EMPTY_MAP;
+ }
+
+ private static void coltMap() {
+ AbstractIntDoubleMap map = new OpenIntDoubleHashMap();
+ map.put(1, 4.5);
+ double value = map.get(1);
+ }
+
+ private static void eclipseCollectionsMap() {
+ MutableIntIntMap mutableIntIntMap = IntIntMaps.mutable.empty();
+ mutableIntIntMap.addToValue(1, 1);
+
+ ImmutableIntIntMap immutableIntIntMap = IntIntMaps.immutable.empty();
+
+ MutableObjectDoubleMap dObject = ObjectDoubleMaps.mutable.empty();
+ dObject.addToValue("price", 150.5);
+ dObject.addToValue("quality", 4.4);
+ dObject.addToValue("stability", 0.8);
+ }
+
+ private static void troveMap() {
+ double[] doubles = new double[] {1.2, 4.5, 0.3};
+ int[] ints = new int[] {1, 4, 0};
+
+ TDoubleIntMap doubleIntMap = new TDoubleIntHashMap(doubles, ints);
+
+ doubleIntMap.put(1.2, 22);
+ doubleIntMap.put(4.5, 16);
+
+ doubleIntMap.adjustValue(1.2, 1);
+ doubleIntMap.adjustValue(4.5, 4);
+ doubleIntMap.adjustValue(0.3, 7);
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java
new file mode 100644
index 0000000000..14610ffb00
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java
@@ -0,0 +1,104 @@
+package com.baeldung.map.sort;
+
+import com.baeldung.map.mergemaps.Employee;
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableSortedMap;
+import com.google.common.collect.Ordering;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class SortHashMap {
+
+ private static Map map = new HashMap<>();
+
+ public static void main(String[] args) {
+
+ initialize();
+
+ treeMapSortByKey();
+
+ arrayListSortByValue();
+ arrayListSortByKey();
+
+ sortStream();
+
+ sortGuava();
+
+ addDuplicates();
+
+ treeSetByKey();
+ treeSetByValue();
+
+ }
+
+ private static void sortGuava() {
+ final Ordering naturalOrdering =
+ Ordering.natural().onResultOf(Functions.forMap(map, null));
+
+ System.out.println(ImmutableSortedMap.copyOf(map, naturalOrdering));
+ }
+
+ private static void sortStream() {
+ map.entrySet().stream()
+ .sorted(Map.Entry.comparingByKey().reversed())
+ .forEach(System.out::println);
+
+ Map result = map.entrySet().stream()
+ .sorted(Map.Entry.comparingByValue())
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
+ (oldValue, newValue) -> oldValue, LinkedHashMap::new));
+
+ result.entrySet().forEach(System.out::println);
+ }
+
+ private static void treeSetByValue() {
+ SortedSet values = new TreeSet<>(map.values());
+ System.out.println(values);
+ }
+
+ private static void treeSetByKey() {
+ SortedSet keysSet = new TreeSet<>(map.keySet());
+ System.out.println(keysSet);
+ }
+
+ private static void treeMapSortByKey() {
+ TreeMap sorted = new TreeMap<>(map);
+ sorted.putAll(map);
+
+ sorted.entrySet().forEach(System.out::println);
+
+ }
+
+ private static void arrayListSortByValue() {
+ List employeeById = new ArrayList<>(map.values());
+
+ Collections.sort(employeeById);
+
+ System.out.println(employeeById);
+ }
+
+ private static void arrayListSortByKey() {
+ List employeeByKey = new ArrayList<>(map.keySet());
+ Collections.sort(employeeByKey);
+ System.out.println(employeeByKey);
+ }
+
+ private static void initialize() {
+ Employee employee1 = new Employee(1L, "Mher");
+ map.put(employee1.getName(), employee1);
+ Employee employee2 = new Employee(22L, "Annie");
+ map.put(employee2.getName(), employee2);
+ Employee employee3 = new Employee(8L, "John");
+ map.put(employee3.getName(), employee3);
+ Employee employee4 = new Employee(2L, "George");
+ map.put(employee4.getName(), employee4);
+ }
+
+ private static void addDuplicates() {
+ Employee employee5 = new Employee(1L, "Mher");
+ map.put(employee5.getName(), employee5);
+ Employee employee6 = new Employee(22L, "Annie");
+ map.put(employee6.getName(), employee6);
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java
new file mode 100644
index 0000000000..ba29d5c454
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java
@@ -0,0 +1,174 @@
+package com.baeldung.map;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class ProductUnitTest {
+
+
+ @Test
+ public void getExistingValue() {
+ HashMap productsByName = new HashMap<>();
+
+ Product eBike = new Product("E-Bike", "A bike with a battery");
+ Product roadBike = new Product("Road bike", "A bike for competition");
+
+ productsByName.put(eBike.getName(), eBike);
+ productsByName.put(roadBike.getName(), roadBike);
+
+ Product nextPurchase = productsByName.get("E-Bike");
+
+ assertEquals("A bike with a battery", nextPurchase.getDescription());
+ }
+
+ @Test
+ public void getNonExistingValue() {
+ HashMap productsByName = new HashMap<>();
+
+ Product eBike = new Product("E-Bike", "A bike with a battery");
+ Product roadBike = new Product("Road bike", "A bike for competition");
+
+ productsByName.put(eBike.getName(), eBike);
+ productsByName.put(roadBike.getName(), roadBike);
+
+ Product nextPurchase = productsByName.get("Car");
+
+ assertNull(nextPurchase);
+ }
+
+ @Test
+ public void getExistingValueAfterSameKeyInsertedTwice() {
+ HashMap productsByName = new HashMap<>();
+
+ Product eBike = new Product("E-Bike", "A bike with a battery");
+ Product roadBike = new Product("Road bike", "A bike for competition");
+ Product newEBike = new Product("E-Bike", "A bike with a better battery");
+
+ productsByName.put(eBike.getName(), eBike);
+ productsByName.put(roadBike.getName(), roadBike);
+ productsByName.put(newEBike.getName(), newEBike);
+
+ Product nextPurchase = productsByName.get("E-Bike");
+
+ assertEquals("A bike with a better battery", nextPurchase.getDescription());
+ }
+
+ @Test
+ public void getExistingValueWithNullKey() {
+ HashMap productsByName = new HashMap<>();
+
+ Product defaultProduct = new Product("Chocolate", "At least buy chocolate");
+
+ productsByName.put(null, defaultProduct);
+ productsByName.put(defaultProduct.getName(), defaultProduct);
+
+ Product nextPurchase = productsByName.get(null);
+ assertEquals("At least buy chocolate", nextPurchase.getDescription());
+
+ nextPurchase = productsByName.get("Chocolate");
+ assertEquals("At least buy chocolate", nextPurchase.getDescription());
+ }
+
+ @Test
+ public void insertSameObjectWithDifferentKey() {
+ HashMap productsByName = new HashMap<>();
+
+ Product defaultProduct = new Product("Chocolate", "At least buy chocolate");
+
+ productsByName.put(null, defaultProduct);
+ productsByName.put(defaultProduct.getName(), defaultProduct);
+
+ assertSame(productsByName.get(null), productsByName.get("Chocolate"));
+ }
+
+ @Test
+ public void checkIfKeyExists() {
+ HashMap productsByName = new HashMap<>();
+
+ Product eBike = new Product("E-Bike", "A bike with a battery");
+
+ productsByName.put(eBike.getName(), eBike);
+
+ assertTrue(productsByName.containsKey("E-Bike"));
+ }
+
+ @Test
+ public void checkIfValueExists() {
+ HashMap productsByName = new HashMap<>();
+
+ Product eBike = new Product("E-Bike", "A bike with a battery");
+
+ productsByName.put(eBike.getName(), eBike);
+
+ assertTrue(productsByName.containsValue(eBike));
+ }
+
+ @Test
+ public void removeExistingKey() {
+ HashMap productsByName = new HashMap<>();
+
+ Product eBike = new Product("E-Bike", "A bike with a battery");
+ Product roadBike = new Product("Road bike", "A bike for competition");
+
+ productsByName.put(eBike.getName(), eBike);
+ productsByName.put(roadBike.getName(), roadBike);
+
+ productsByName.remove("E-Bike");
+
+ assertNull(productsByName.get("E-Bike"));
+ }
+
+ @Test
+ public void givenMutableKeyWhenKeyChangeThenValueNotFound() {
+ // Given
+ MutableKey key = new MutableKey("initial");
+
+ Map items = new HashMap<>();
+ items.put(key, "success");
+
+ // When
+ key.setName("changed");
+
+ // Then
+ assertNull(items.get(key));
+ }
+
+ static class MutableKey {
+ private String name;
+
+ public MutableKey(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ MutableKey that = (MutableKey) o;
+ return Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java
new file mode 100644
index 0000000000..4517dea328
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java
@@ -0,0 +1,48 @@
+package com.baeldung.map.convert;
+
+import org.apache.commons.collections4.MapUtils;
+import org.junit.Assert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MapToStringUnitTest {
+
+ private Map wordsByKey = new HashMap<>();
+
+ @BeforeEach
+ public void setup() {
+ wordsByKey.clear();
+ wordsByKey.put(1, "one");
+ wordsByKey.put(2, "two");
+ wordsByKey.put(3, "three");
+ wordsByKey.put(4, "four");
+ }
+
+ @Test
+ public void givenMap_WhenUsingIteration_ThenResultingMapIsCorrect() {
+ String mapAsString = MapToString.convertWithIteration(wordsByKey);
+ Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString);
+ }
+
+ @Test
+ public void givenMap_WhenUsingStream_ThenResultingMapIsCorrect() {
+ String mapAsString = MapToString.convertWithStream(wordsByKey);
+ Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString);
+ }
+
+ @Test
+ public void givenMap_WhenUsingGuava_ThenResultingMapIsCorrect() {
+ String mapAsString = MapToString.convertWithGuava(wordsByKey);
+ Assert.assertEquals("1=one,2=two,3=three,4=four", mapAsString);
+ }
+
+ @Test
+ public void givenMap_WhenUsingApache_ThenResultingMapIsCorrect() {
+ String mapAsString = MapToString.convertWithApache(wordsByKey);
+ Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString);
+ MapUtils.debugPrint(System.out, "Map as String", wordsByKey);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java
new file mode 100644
index 0000000000..2f80b30871
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.map.convert;
+
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+public class StringToMapUnitTest {
+
+ @Test
+ public void givenString_WhenUsingStream_ThenResultingStringIsCorrect() {
+ Map wordsByKey = StringToMap.convertWithStream("1=one,2=two,3=three,4=four");
+ Assert.assertEquals(4, wordsByKey.size());
+ Assert.assertEquals("one", wordsByKey.get("1"));
+ }
+
+ @Test
+ void givenString_WhenUsingGuava_ThenResultingStringIsCorrect() {
+ Map wordsByKey = StringToMap.convertWithGuava("1=one,2=two,3=three,4=four");
+ Assert.assertEquals(4, wordsByKey.size());
+ Assert.assertEquals("one", wordsByKey.get("1"));
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java
new file mode 100644
index 0000000000..e2d5e327e1
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java
@@ -0,0 +1,76 @@
+package com.baeldung.map.copyhashmap;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CopyHashMapUnitTest {
+
+ @Test
+ public void givenHashMap_whenShallowCopy_thenCopyisNotSameAsOriginal() {
+
+ HashMap map = new HashMap<>();
+ Employee emp1 = new Employee("John");
+ Employee emp2 = new Employee("Norman");
+ map.put("emp1",emp1);
+ map.put("emp2",emp2);
+
+ HashMap shallowCopy = CopyHashMap.shallowCopy(map);
+
+ assertThat(shallowCopy).isNotSameAs(map);
+
+ }
+
+ @Test
+ public void givenHashMap_whenShallowCopyModifyingOriginalObject_thenCopyShouldChange() {
+
+ HashMap map = new HashMap<>();
+ Employee emp1 = new Employee("John");
+ Employee emp2 = new Employee("Norman");
+ map.put("emp1",emp1);
+ map.put("emp2",emp2);
+
+ HashMap shallowCopy = CopyHashMap.shallowCopy(map);
+
+ emp1.setName("Johny");
+
+ assertThat(shallowCopy.get("emp1")).isEqualTo(map.get("emp1"));
+
+ }
+
+ @Test
+ public void givenHashMap_whenDeepCopyModifyingOriginalObject_thenCopyShouldNotChange() {
+
+ HashMap map = new HashMap<>();
+ Employee emp1 = new Employee("John");
+ Employee emp2 = new Employee("Norman");
+ map.put("emp1",emp1);
+ map.put("emp2",emp2);
+ HashMap deepCopy = CopyHashMap.deepCopy(map);
+
+ emp1.setName("Johny");
+
+ assertThat(deepCopy.get("emp1")).isNotEqualTo(map.get("emp1"));
+
+ }
+
+ @Test
+ public void givenImmutableMap_whenCopyUsingGuava_thenCopyShouldNotChange() {
+ Employee emp1 = new Employee("John");
+ Employee emp2 = new Employee("Norman");
+
+ Map map = ImmutableMap. builder()
+ .put("emp1",emp1)
+ .put("emp2",emp2)
+ .build();
+ Map shallowCopy = ImmutableMap.copyOf(map);
+
+ assertThat(shallowCopy).isSameAs(map);
+
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java
new file mode 100644
index 0000000000..5db55c26ea
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java
@@ -0,0 +1,28 @@
+package com.baeldung.map.copyhashmap;
+
+import java.io.Serializable;
+
+public class Employee implements Serializable{
+
+ private String name;
+
+ public Employee(String name) {
+ super();
+ this.name = name;
+ }
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
+
+}
+
+
diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java
new file mode 100644
index 0000000000..7c6dffe787
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.map.initialize;
+
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class MapInitializerUnitTest {
+
+ @Test
+ public void givenStaticMap_whenUpdated_thenCorrect() {
+
+ MapInitializer.articleMapOne.put("NewArticle1", "Convert array to List");
+
+ assertEquals(MapInitializer.articleMapOne.get("NewArticle1"), "Convert array to List");
+
+ }
+
+ @Test(expected=UnsupportedOperationException.class)
+ public void givenSingleTonMap_whenEntriesAdded_throwsException() {
+
+ Map map = MapInitializer.createSingletonMap();
+ map.put("username2", "password2");
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java
new file mode 100644
index 0000000000..30b945bfc8
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java
@@ -0,0 +1,58 @@
+package com.baeldung.map.mapmax;
+
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class MapMaxUnitTest {
+
+ Map map = null;
+ MapMax mapMax = null;
+
+
+ @Before
+ public void setupTestData() {
+ map = new HashMap();
+ map.put(23, 12);
+ map.put(46, 24);
+ map.put(27, 38);
+ mapMax = new MapMax();
+ }
+
+ @Test
+ public void givenMap_whenIterated_thenReturnMaxValue() {
+ assertEquals(new Integer(38), mapMax.maxUsingIteration(map));
+ }
+
+ @Test
+ public void givenMap_whenUsingCollectionsMax_thenReturnMaxValue() {
+ assertEquals(new Integer(38), mapMax.maxUsingCollectionsMax(map));
+ }
+
+ @Test
+ public void givenMap_whenUsingCollectionsMaxAndLambda_thenReturnMaxValue() {
+ assertEquals(new Integer(38), mapMax.maxUsingCollectionsMaxAndLambda(map));
+ }
+
+ @Test
+ public void givenMap_whenUsingCollectionsMaxAndMethodReference_thenReturnMaxValue() {
+ assertEquals(new Integer(38), mapMax.maxUsingCollectionsMaxAndMethodReference(map));
+ }
+
+ @Test
+ public void givenMap_whenUsingStreamAndLambda_thenReturnMaxValue() {
+ assertEquals(new Integer(38), mapMax.maxUsingStreamAndLambda(map));
+ }
+
+ @Test
+ public void givenMap_whenUsingStreamAndMethodReference_thenReturnMaxValue() {
+ assertEquals(new Integer(38), mapMax.maxUsingStreamAndMethodReference (map));
+ }
+
+
+}
diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java
new file mode 100644
index 0000000000..293f24c378
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java
@@ -0,0 +1,72 @@
+package com.baeldung.map.weakhashmap;
+
+
+import org.junit.Test;
+
+import java.util.WeakHashMap;
+import java.util.concurrent.TimeUnit;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static org.junit.Assert.assertTrue;
+
+public class WeakHashMapUnitTest {
+
+ @Test
+ public void givenWeakHashMap_whenCacheValueThatHasNoReferenceToIt_GCShouldReclaimThatObject() {
+ //given
+ WeakHashMap map = new WeakHashMap<>();
+ BigImage bigImage = new BigImage("image_id");
+ UniqueImageName imageName = new UniqueImageName("name_of_big_image");
+
+ map.put(imageName, bigImage);
+ assertTrue(map.containsKey(imageName));
+
+ //when big image key is not reference anywhere
+ imageName = null;
+ System.gc();
+
+ //then GC will finally reclaim that object
+ await().atMost(10, TimeUnit.SECONDS).until(map::isEmpty);
+ }
+
+ @Test
+ public void givenWeakHashMap_whenCacheValueThatHasNoReferenceToIt_GCShouldReclaimThatObjectButLeaveReferencedObject() {
+ //given
+ WeakHashMap map = new WeakHashMap<>();
+ BigImage bigImageFirst = new BigImage("foo");
+ UniqueImageName imageNameFirst = new UniqueImageName("name_of_big_image");
+
+ BigImage bigImageSecond = new BigImage("foo_2");
+ UniqueImageName imageNameSecond = new UniqueImageName("name_of_big_image_2");
+
+ map.put(imageNameFirst, bigImageFirst);
+ map.put(imageNameSecond, bigImageSecond);
+ assertTrue(map.containsKey(imageNameFirst));
+ assertTrue(map.containsKey(imageNameSecond));
+
+ //when
+ imageNameFirst = null;
+ System.gc();
+
+ //then
+ await().atMost(10, TimeUnit.SECONDS).until(() -> map.size() == 1);
+ await().atMost(10, TimeUnit.SECONDS).until(() -> map.containsKey(imageNameSecond));
+ }
+
+
+ class BigImage {
+ public final String imageId;
+
+ BigImage(String imageId) {
+ this.imageId = imageId;
+ }
+ }
+
+ class UniqueImageName {
+ public final String imageName;
+
+ UniqueImageName(String imageName) {
+ this.imageName = imageName;
+ }
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps-3/README.md b/core-java-modules/core-java-collections-maps-3/README.md
new file mode 100644
index 0000000000..142aa34800
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-3/README.md
@@ -0,0 +1,8 @@
+## Java Collections Cookbooks and Examples
+
+This module contains articles about Map data structures in Java.
+
+### Relevant Articles:
+- [Java TreeMap vs HashMap](https://www.baeldung.com/java-treemap-vs-hashmap)
+- [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps)
+- More articles: [[<-- prev]](/core-java-collections-maps-2)
diff --git a/core-java-modules/core-java-collections-maps-3/pom.xml b/core-java-modules/core-java-collections-maps-3/pom.xml
new file mode 100644
index 0000000000..95414c12c2
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-3/pom.xml
@@ -0,0 +1,26 @@
+
+
+ 4.0.0
+ core-java-collections-maps-3
+ 0.1.0-SNAPSHOT
+ core-java-collections-maps-3
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../../parent-java
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java
new file mode 100644
index 0000000000..0edd0cd87b
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java
@@ -0,0 +1,225 @@
+package com.baeldung.map.compare;
+
+import com.google.common.base.Equivalence;
+import com.google.common.collect.MapDifference;
+import com.google.common.collect.MapDifference.ValueDifference;
+import com.google.common.collect.Maps;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.collection.IsMapContaining.hasEntry;
+import static org.hamcrest.collection.IsMapContaining.hasKey;
+import static org.junit.Assert.*;
+
+public class HashMapComparisonUnitTest {
+
+ Map asiaCapital1;
+ Map asiaCapital2;
+ Map asiaCapital3;
+
+ Map asiaCity1;
+ Map asiaCity2;
+ Map asiaCity3;
+
+ @Before
+ public void setup(){
+ asiaCapital1 = new HashMap();
+ asiaCapital1.put("Japan", "Tokyo");
+ asiaCapital1.put("South Korea", "Seoul");
+
+ asiaCapital2 = new HashMap();
+ asiaCapital2.put("South Korea", "Seoul");
+ asiaCapital2.put("Japan", "Tokyo");
+
+ asiaCapital3 = new HashMap();
+ asiaCapital3.put("Japan", "Tokyo");
+ asiaCapital3.put("China", "Beijing");
+
+ asiaCity1 = new HashMap();
+ asiaCity1.put("Japan", new String[] { "Tokyo", "Osaka" });
+ asiaCity1.put("South Korea", new String[] { "Seoul", "Busan" });
+
+ asiaCity2 = new HashMap();
+ asiaCity2.put("South Korea", new String[] { "Seoul", "Busan" });
+ asiaCity2.put("Japan", new String[] { "Tokyo", "Osaka" });
+
+ asiaCity3 = new HashMap();
+ asiaCity3.put("Japan", new String[] { "Tokyo", "Osaka" });
+ asiaCity3.put("China", new String[] { "Beijing", "Hong Kong" });
+ }
+
+ @Test
+ public void whenCompareTwoHashMapsUsingEquals_thenSuccess() {
+ assertTrue(asiaCapital1.equals(asiaCapital2));
+ assertFalse(asiaCapital1.equals(asiaCapital3));
+ }
+
+ @Test
+ public void whenCompareTwoHashMapsWithArrayValuesUsingEquals_thenFail() {
+ assertFalse(asiaCity1.equals(asiaCity2));
+ }
+
+ @Test
+ public void whenCompareTwoHashMapsUsingStreamAPI_thenSuccess() {
+ assertTrue(areEqual(asiaCapital1, asiaCapital2));
+ assertFalse(areEqual(asiaCapital1, asiaCapital3));
+ }
+
+ @Test
+ public void whenCompareTwoHashMapsWithArrayValuesUsingStreamAPI_thenSuccess() {
+ assertTrue(areEqualWithArrayValue(asiaCity1, asiaCity2));
+ assertFalse(areEqualWithArrayValue(asiaCity1, asiaCity3));
+ }
+
+ @Test
+ public void whenCompareTwoHashMapKeys_thenSuccess() {
+ assertTrue(asiaCapital1.keySet().equals(asiaCapital2.keySet()));
+ assertFalse(asiaCapital1.keySet().equals(asiaCapital3.keySet()));
+ }
+
+ @Test
+ public void whenCompareTwoHashMapKeyValuesUsingStreamAPI_thenSuccess() {
+ Map asiaCapital3 = new HashMap();
+ asiaCapital3.put("Japan", "Tokyo");
+ asiaCapital3.put("South Korea", "Seoul");
+ asiaCapital3.put("China", "Beijing");
+
+ Map asiaCapital4 = new HashMap();
+ asiaCapital4.put("South Korea", "Seoul");
+ asiaCapital4.put("Japan", "Osaka");
+ asiaCapital4.put("China", "Beijing");
+
+ Map result = areEqualKeyValues(asiaCapital3, asiaCapital4);
+
+ assertEquals(3, result.size());
+ assertThat(result, hasEntry("Japan", false));
+ assertThat(result, hasEntry("South Korea", true));
+ assertThat(result, hasEntry("China", true));
+ }
+
+ @Test
+ public void givenDifferentMaps_whenGetDiffUsingGuava_thenSuccess() {
+ Map asia1 = new HashMap();
+ asia1.put("Japan", "Tokyo");
+ asia1.put("South Korea", "Seoul");
+ asia1.put("India", "New Delhi");
+
+ Map asia2 = new HashMap();
+ asia2.put("Japan", "Tokyo");
+ asia2.put("China", "Beijing");
+ asia2.put("India", "Delhi");
+
+ MapDifference diff = Maps.difference(asia1, asia2);
+ Map> entriesDiffering = diff.entriesDiffering();
+
+ assertFalse(diff.areEqual());
+ assertEquals(1, entriesDiffering.size());
+ assertThat(entriesDiffering, hasKey("India"));
+ assertEquals("New Delhi", entriesDiffering.get("India").leftValue());
+ assertEquals("Delhi", entriesDiffering.get("India").rightValue());
+ }
+
+ @Test
+ public void givenDifferentMaps_whenGetEntriesOnOneSideUsingGuava_thenSuccess() {
+ Map asia1 = new HashMap();
+ asia1.put("Japan", "Tokyo");
+ asia1.put("South Korea", "Seoul");
+ asia1.put("India", "New Delhi");
+
+ Map asia2 = new HashMap();
+ asia2.put("Japan", "Tokyo");
+ asia2.put("China", "Beijing");
+ asia2.put("India", "Delhi");
+
+ MapDifference diff = Maps.difference(asia1, asia2);
+ Map entriesOnlyOnRight = diff.entriesOnlyOnRight();
+ Map entriesOnlyOnLeft = diff.entriesOnlyOnLeft();
+
+ assertEquals(1, entriesOnlyOnRight.size());
+ assertThat(entriesOnlyOnRight, hasEntry("China", "Beijing"));
+ assertEquals(1, entriesOnlyOnLeft.size());
+ assertThat(entriesOnlyOnLeft, hasEntry("South Korea", "Seoul"));
+ }
+
+ @Test
+ public void givenDifferentMaps_whenGetCommonEntriesUsingGuava_thenSuccess() {
+ Map asia1 = new HashMap();
+ asia1.put("Japan", "Tokyo");
+ asia1.put("South Korea", "Seoul");
+ asia1.put("India", "New Delhi");
+
+ Map asia2 = new HashMap();
+ asia2.put("Japan", "Tokyo");
+ asia2.put("China", "Beijing");
+ asia2.put("India", "Delhi");
+
+ MapDifference diff = Maps.difference(asia1, asia2);
+ Map entriesInCommon = diff.entriesInCommon();
+
+ assertEquals(1, entriesInCommon.size());
+ assertThat(entriesInCommon, hasEntry("Japan", "Tokyo"));
+ }
+
+ @Test
+ public void givenSimilarMapsWithArrayValue_whenCompareUsingGuava_thenFail() {
+ MapDifference diff = Maps.difference(asiaCity1, asiaCity2);
+ assertFalse(diff.areEqual());
+ }
+
+ @Test
+ public void givenSimilarMapsWithArrayValue_whenCompareUsingGuavaEquivalence_thenSuccess() {
+ Equivalence eq = new Equivalence() {
+ @Override
+ protected boolean doEquivalent(String[] a, String[] b) {
+ return Arrays.equals(a, b);
+ }
+
+ @Override
+ protected int doHash(String[] value) {
+ return value.hashCode();
+ }
+ };
+
+ MapDifference diff = Maps.difference(asiaCity1, asiaCity2, eq);
+ assertTrue(diff.areEqual());
+
+ diff = Maps.difference(asiaCity1, asiaCity3, eq);
+ assertFalse(diff.areEqual());
+ }
+
+ // ===========================================================================
+
+ private boolean areEqual(Map first, Map second) {
+ if (first.size() != second.size()) {
+ return false;
+ }
+
+ return first.entrySet()
+ .stream()
+ .allMatch(e -> e.getValue()
+ .equals(second.get(e.getKey())));
+ }
+
+ private boolean areEqualWithArrayValue(Map first, Map second) {
+ if (first.size() != second.size()) {
+ return false;
+ }
+
+ return first.entrySet()
+ .stream()
+ .allMatch(e -> Arrays.equals(e.getValue(), second.get(e.getKey())));
+ }
+
+ private Map areEqualKeyValues(Map first, Map second) {
+ return first.entrySet()
+ .stream()
+ .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().equals(second.get(e.getKey()))));
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java
new file mode 100644
index 0000000000..1057e3b9f0
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java
@@ -0,0 +1,58 @@
+package com.baeldung.map.treemaphashmap;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class TreeMapVsHashMapUnitTest {
+
+ @Test
+ public void whenInsertObjectsTreeMap_thenNaturalOrder() {
+ Map treemap = new TreeMap<>();
+ treemap.put(3, "TreeMap");
+ treemap.put(2, "vs");
+ treemap.put(1, "HashMap");
+ Assert.assertThat(treemap.keySet(), Matchers.contains(1, 2, 3));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void whenInsertNullInTreeMap_thenException() {
+ Map treemap = new TreeMap<>();
+ treemap.put(null, "NullPointerException");
+ }
+
+ @Test
+ public void whenInsertObjectsHashMap_thenRandomOrder() {
+ Map hashmap = new HashMap<>();
+ hashmap.put(3, "TreeMap");
+ hashmap.put(2, "vs");
+ hashmap.put(1, "HashMap");
+ Assert.assertThat(hashmap.keySet(), Matchers.containsInAnyOrder(1, 2, 3));
+ }
+
+ @Test
+ public void whenInsertNullInHashMap_thenInsertsNull() {
+ Map hashmap = new HashMap<>();
+ hashmap.put(null, null);
+ Assert.assertNull(hashmap.get(null));
+ }
+
+ @Test
+ public void givenHashMapAndTreeMap_whenputDuplicates_thenOnlyUnique() {
+ Map treeMap = new HashMap<>();
+ treeMap.put(1, "Baeldung");
+ treeMap.put(1, "Baeldung");
+
+ Assert.assertTrue(treeMap.size() == 1);
+
+ Map treeMap2 = new TreeMap<>();
+ treeMap2.put(1, "Baeldung");
+ treeMap2.put(1, "Baeldung");
+
+ Assert.assertTrue(treeMap2.size() == 1);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps/README.md b/core-java-modules/core-java-collections-maps/README.md
new file mode 100644
index 0000000000..1323fb97cd
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps/README.md
@@ -0,0 +1,16 @@
+## Java Collections Cookbooks and Examples
+
+This module contains articles about Map data structures in Java.
+
+### Relevant Articles:
+- [Guide to the Guava BiMap](https://www.baeldung.com/guava-bimap)
+- [A Guide to Java HashMap](https://www.baeldung.com/java-hashmap)
+- [A Guide to LinkedHashMap in Java](https://www.baeldung.com/java-linked-hashmap)
+- [A Guide to TreeMap in Java](https://www.baeldung.com/java-treemap)
+- [How to Store Duplicate Keys in a Map in Java?](https://www.baeldung.com/java-map-duplicate-keys)
+- [Get the Key for a Value from a Java Map](https://www.baeldung.com/java-map-key-from-value)
+- [How to Check If a Key Exists in a Map](https://www.baeldung.com/java-map-key-exists)
+- [Immutable Map Implementations in Java](https://www.baeldung.com/java-immutable-maps)
+- [Guide to Apache Commons MultiValuedMap](https://www.baeldung.com/apache-commons-multi-valued-map)
+- [The Java HashMap Under the Hood](https://www.baeldung.com/java-hashmap-advanced)
+- More articles: [[next -->]](/core-java-collections-maps-2)
diff --git a/core-java-modules/core-java-collections-maps/pom.xml b/core-java-modules/core-java-collections-maps/pom.xml
new file mode 100644
index 0000000000..c0dd705c1c
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+ core-java-collections-maps
+ 0.1.0-SNAPSHOT
+ core-java-collections-maps
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../../parent-java
+
+
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+
+
+ 4.1
+ 3.6.1
+
+
diff --git a/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java
new file mode 100644
index 0000000000..91b7197a92
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java
@@ -0,0 +1,44 @@
+/**
+ *
+ */
+package com.baeldung.map;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+ * @author swpraman
+ *
+ */
+public class MapUtil {
+
+ public static Stream keys(Map map, V value) {
+ return map.entrySet()
+ .stream()
+ .filter(entry -> value.equals(entry.getValue()))
+ .map(Map.Entry::getKey);
+ }
+
+ public static Set getKeys(Map map, V value) {
+ Set keys = new HashSet<>();
+ for (Entry entry : map.entrySet()) {
+ if (entry.getValue().equals(value)) {
+ keys.add(entry.getKey());
+ }
+ }
+ return keys;
+ }
+
+ public static K getKey(Map map, V value) {
+ for (Entry entry : map.entrySet()) {
+ if (entry.getValue().equals(value)) {
+ return entry.getKey();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyKey.java b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyKey.java
new file mode 100644
index 0000000000..9993d7862c
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyKey.java
@@ -0,0 +1,64 @@
+package com.baeldung.map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MyKey {
+ private static final Logger LOG = LoggerFactory.getLogger(MyKey.class);
+
+ private String name;
+ private int id;
+
+ public MyKey(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ @Override
+ public int hashCode() {
+ LOG.debug("Calling hashCode()");
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "MyKey [name=" + name + ", id=" + id + "]";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ LOG.debug("Calling equals() for key: " + obj);
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ MyKey other = (MyKey) obj;
+ if (id != other.id)
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java
new file mode 100644
index 0000000000..b687e57d85
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java
@@ -0,0 +1,23 @@
+package com.baeldung.map;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class MyLinkedHashMap extends LinkedHashMap {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private static final int MAX_ENTRIES = 5;
+
+ public MyLinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {
+ super(initialCapacity, loadFactor, accessOrder);
+ }
+
+ @Override
+ protected boolean removeEldestEntry(Map.Entry eldest) {
+ return size() > MAX_ENTRIES;
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps/src/main/resources/logback.xml b/core-java-modules/core-java-collections-maps/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java
new file mode 100644
index 0000000000..b44d2db1aa
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java
@@ -0,0 +1,120 @@
+package com.baeldung.guava;
+
+import static org.junit.Assert.*;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.EnumHashBiMap;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.ImmutableBiMap;
+
+public class GuavaBiMapUnitTest {
+ @Test
+ public void whenQueryByValue_returnsKey() {
+ final BiMap capitalCountryBiMap = HashBiMap.create();
+ capitalCountryBiMap.put("New Delhi", "India");
+ capitalCountryBiMap.put("Washingon, D.C.", "USA");
+ capitalCountryBiMap.put("Moscow", "Russia");
+
+ final String countryCapitalName = capitalCountryBiMap.inverse().get("India");
+
+ assertEquals("New Delhi", countryCapitalName);
+ }
+
+ @Test
+ public void whenCreateBiMapFromExistingMap_returnsKey() {
+ final Map capitalCountryMap = new HashMap<>();
+ capitalCountryMap.put("New Delhi", "India");
+ capitalCountryMap.put("Washingon, D.C.", "USA");
+ capitalCountryMap.put("Moscow", "Russia");
+ final BiMap capitalCountryBiMap = HashBiMap.create(capitalCountryMap);
+
+ final String countryCapitalName = capitalCountryBiMap.inverse().get("India");
+
+ assertEquals("New Delhi", countryCapitalName);
+ }
+
+ @Test
+ public void whenQueryByKey_returnsValue() {
+ final BiMap capitalCountryBiMap = HashBiMap.create();
+
+ capitalCountryBiMap.put("New Delhi", "India");
+ capitalCountryBiMap.put("Washingon, D.C.", "USA");
+ capitalCountryBiMap.put("Moscow", "Russia");
+
+ assertEquals("USA", capitalCountryBiMap.get("Washingon, D.C."));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void whenSameValueIsPresent_throwsException() {
+ final BiMap capitalCountryBiMap = HashBiMap.create();
+
+ capitalCountryBiMap.put("New Delhi", "India");
+ capitalCountryBiMap.put("Washingon, D.C.", "USA");
+ capitalCountryBiMap.put("Moscow", "Russia");
+ capitalCountryBiMap.put("Trump", "USA");
+ }
+
+ @Test
+ public void givenSameValueIsPresent_whenForcePut_completesSuccessfully() {
+ final BiMap capitalCountryBiMap = HashBiMap.create();
+
+ capitalCountryBiMap.put("New Delhi", "India");
+ capitalCountryBiMap.put("Washingon, D.C.", "USA");
+ capitalCountryBiMap.put("Moscow", "Russia");
+ capitalCountryBiMap.forcePut("Trump", "USA");
+
+ assertEquals("USA", capitalCountryBiMap.get("Trump"));
+ assertEquals("Trump", capitalCountryBiMap.inverse().get("USA"));
+ }
+
+ @Test
+ public void whenSameKeyIsPresent_replacesAlreadyPresent() {
+ final BiMap capitalCountryBiMap = HashBiMap.create();
+
+ capitalCountryBiMap.put("New Delhi", "India");
+ capitalCountryBiMap.put("Washingon, D.C.", "USA");
+ capitalCountryBiMap.put("Moscow", "Russia");
+ capitalCountryBiMap.put("Washingon, D.C.", "HongKong");
+
+ assertEquals("HongKong", capitalCountryBiMap.get("Washingon, D.C."));
+ }
+
+ @Test
+ public void whenUsingImmutableBiMap_allowsPutSuccessfully() {
+ final BiMap capitalCountryBiMap = new ImmutableBiMap.Builder().put("New Delhi", "India").put("Washingon, D.C.", "USA").put("Moscow", "Russia").build();
+
+ assertEquals("USA", capitalCountryBiMap.get("Washingon, D.C."));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void whenUsingImmutableBiMap_doesntAllowRemove() {
+ final BiMap capitalCountryBiMap = new ImmutableBiMap.Builder().put("New Delhi", "India").put("Washingon, D.C.", "USA").put("Moscow", "Russia").build();
+
+ capitalCountryBiMap.remove("New Delhi");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void whenUsingImmutableBiMap_doesntAllowPut() {
+ final BiMap capitalCountryBiMap = new ImmutableBiMap.Builder().put("New Delhi", "India").put("Washingon, D.C.", "USA").put("Moscow", "Russia").build();
+
+ capitalCountryBiMap.put("New York", "USA");
+ }
+
+ private enum Operation {
+ ADD, SUBTRACT, MULTIPLY, DIVIDE
+ }
+
+ @Test
+ public void whenUsingEnumAsKeyInMap_replacesAlreadyPresent() {
+ final BiMap operationStringBiMap = EnumHashBiMap.create(Operation.class);
+
+ operationStringBiMap.put(Operation.ADD, "Add");
+ operationStringBiMap.put(Operation.SUBTRACT, "Subtract");
+ operationStringBiMap.put(Operation.MULTIPLY, "Multiply");
+ operationStringBiMap.put(Operation.DIVIDE, "Divide");
+
+ assertEquals("Divide", operationStringBiMap.get(Operation.DIVIDE));
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java
new file mode 100644
index 0000000000..d308aac7eb
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java
@@ -0,0 +1,84 @@
+package com.baeldung.map;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+
+public class ImmutableMapUnitTest {
+
+ @Test
+ public void whenCollectionsUnModifiableMapMethod_thenOriginalCollectionChangesReflectInUnmodifiableMap() {
+
+ Map mutableMap = new HashMap<>();
+ mutableMap.put("USA", "North America");
+
+ Map unmodifiableMap = Collections.unmodifiableMap(mutableMap);
+ assertThrows(UnsupportedOperationException.class, () -> unmodifiableMap.put("Canada", "North America"));
+
+ mutableMap.remove("USA");
+ assertFalse(unmodifiableMap.containsKey("USA"));
+
+ mutableMap.put("Mexico", "North America");
+ assertTrue(unmodifiableMap.containsKey("Mexico"));
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void whenGuavaImmutableMapFromCopyOfMethod_thenOriginalCollectionChangesDoNotReflectInImmutableMap() {
+
+ Map mutableMap = new HashMap<>();
+ mutableMap.put("USA", "North America");
+
+ ImmutableMap immutableMap = ImmutableMap.copyOf(mutableMap);
+ assertTrue(immutableMap.containsKey("USA"));
+
+ assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America"));
+
+ mutableMap.remove("USA");
+ assertTrue(immutableMap.containsKey("USA"));
+
+ mutableMap.put("Mexico", "North America");
+ assertFalse(immutableMap.containsKey("Mexico"));
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void whenGuavaImmutableMapFromBuilderMethod_thenOriginalCollectionChangesDoNotReflectInImmutableMap() {
+
+ Map mutableMap = new HashMap<>();
+ mutableMap.put("USA", "North America");
+
+ ImmutableMap immutableMap = ImmutableMap.builder()
+ .putAll(mutableMap)
+ .put("Costa Rica", "North America")
+ .build();
+ assertTrue(immutableMap.containsKey("USA"));
+ assertTrue(immutableMap.containsKey("Costa Rica"));
+
+ assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America"));
+
+ mutableMap.remove("USA");
+ assertTrue(immutableMap.containsKey("USA"));
+
+ mutableMap.put("Mexico", "North America");
+ assertFalse(immutableMap.containsKey("Mexico"));
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void whenGuavaImmutableMapFromOfMethod_thenOriginalCollectionChangesDoNotReflectInImmutableMap() {
+
+ ImmutableMap immutableMap = ImmutableMap.of("USA", "North America", "Costa Rica", "North America");
+ assertTrue(immutableMap.containsKey("USA"));
+ assertTrue(immutableMap.containsKey("Costa Rica"));
+
+ assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America"));
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java
new file mode 100644
index 0000000000..dbad2e5b5e
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.map;
+
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+public class KeyCheckUnitTest {
+
+ @Test
+ public void whenKeyIsPresent_thenContainsKeyReturnsTrue() {
+ Map map = Collections.singletonMap("key", "value");
+
+ assertTrue(map.containsKey("key"));
+ assertFalse(map.containsKey("missing"));
+ }
+
+ @Test
+ public void whenKeyHasNullValue_thenGetStillWorks() {
+ Map map = Collections.singletonMap("nothing", null);
+
+ assertTrue(map.containsKey("nothing"));
+ assertNull(map.get("nothing"));
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java
new file mode 100644
index 0000000000..721b48ea7b
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java
@@ -0,0 +1,119 @@
+package com.baeldung.map;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.TreeMultimap;
+import org.apache.commons.collections4.MultiMap;
+import org.apache.commons.collections4.MultiMapUtils;
+import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.map.MultiValueMap;
+import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
+import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class MapMultipleValuesUnitTest {
+ private static final Logger LOG = LoggerFactory.getLogger(MapMultipleValuesUnitTest.class);
+
+ @Test
+ public void givenHashMap_whenPuttingTwice_thenReturningFirstValue() {
+ Map map = new HashMap<>();
+ assertThat(map.put("key1", "value1")).isEqualTo(null);
+ assertThat(map.put("key1", "value2")).isEqualTo("value1");
+ assertThat(map.get("key1")).isEqualTo("value2");
+ }
+
+ @Test
+ public void givenCollectionAsValue_whenPuttingTwice_thenReturningCollection() {
+ Map> map = new HashMap<>();
+ List list = new ArrayList<>();
+ map.put("key1", list);
+ map.get("key1").add("value1");
+ map.get("key1").add("value2");
+ assertThat(map.get("key1").get(0)).isEqualTo("value1");
+ assertThat(map.get("key1").get(1)).isEqualTo("value2");
+ }
+
+ @Test
+ public void givenCollectionAsValueAndJava8_whenPuttingTwice_thenReturningCollection() {
+ Map> map = new HashMap<>();
+ map.computeIfAbsent("key1", k -> new ArrayList<>()).add("value1");
+ map.computeIfAbsent("key1", k -> new ArrayList<>()).add("value2");
+ assertThat(map.get("key1").get(0)).isEqualTo("value1");
+ assertThat(map.get("key1").get(1)).isEqualTo("value2");
+ }
+
+ @Test
+ public void givenMultiValueMap_whenPuttingTwice_thenReturningValues() {
+ MultiMap map = new MultiValueMap<>();
+ map.put("key1", "value1");
+ map.put("key1", "value2");
+ assertThat((Collection) map.get("key1"))
+ .contains("value1", "value2");
+ }
+
+ @Test
+ public void givenArrayListValuedHashMap_whenPuttingDoubleValues_thenReturningAllValues() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key1", "value1");
+ map.put("key1", "value2");
+ map.put("key1", "value2");
+ assertThat((Collection) map.get("key1"))
+ .containsExactly("value1", "value2", "value2");
+ }
+
+ @Test
+ public void givenHashSetValuedHashMap_whenPuttingTwiceTheSame_thenReturningOneValue() {
+ MultiValuedMap map = new HashSetValuedHashMap<>();
+ map.put("key1", "value1");
+ map.put("key1", "value1");
+ assertThat((Collection) map.get("key1"))
+ .containsExactly("value1");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key1", "value1");
+ map.put("key1", "value2");
+ MultiValuedMap immutableMap =
+ MultiMapUtils.unmodifiableMultiValuedMap(map);
+ immutableMap.put("key1", "value3");
+ }
+
+ @Test
+ public void givenArrayListMultiMap_whenInserting_thenCorrectOutput() {
+ Multimap map = ArrayListMultimap.create();
+ map.put("key1", "value2");
+ map.put("key1", "value1");
+ assertThat((Collection) map.get("key1"))
+ .containsExactly("value2", "value1");
+ }
+
+ @Test
+ public void givenLinkedHashMultiMap_whenInserting_thenReturningValuesInInsertionOrder() {
+ Multimap map = LinkedHashMultimap.create();
+ map.put("key1", "value3");
+ map.put("key1", "value1");
+ map.put("key1", "value2");
+ assertThat((Collection) map.get("key1"))
+ .containsExactly("value3", "value1", "value2");
+ }
+
+ @Test
+ public void givenTreeMultimap_whenInserting_thenReturningValuesInNaturalOrder() {
+ Multimap map = TreeMultimap.create();
+ map.put("key1", "value3");
+ map.put("key1", "value1");
+ map.put("key1", "value2");
+ assertThat((Collection