Skip to content

Commit 9ad48a7

Browse files
kahgohmanumafe98
andauthored
Add maps concept (#2914)
--------- Co-authored-by: Manuel Maxera <[email protected]>
1 parent f5685d2 commit 9ad48a7

File tree

20 files changed

+1144
-6
lines changed

20 files changed

+1144
-6
lines changed

concepts/maps/.meta/config.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"blurb": "Maps are a collection of key value pairs.",
3+
"authors": [
4+
"kahgoh"
5+
],
6+
"contributors": []
7+
}

concepts/maps/about.md

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
# About Maps
2+
3+
A **Map** is a data structure for storing key value pairs.
4+
It is similar to dictionaries in other programming languages.
5+
The [Map][map-javadoc] interface defines the operations you can make with a map.
6+
7+
## HashMap
8+
9+
Java has a number of different Map implementations.
10+
[HashMap][hashmap-javadoc] is a commonly used one.
11+
12+
```java
13+
// Make an instance
14+
Map<String, Integer> fruitPrices = new HashMap<>();
15+
```
16+
17+
~~~~exercism/note
18+
When defining a `Map` variable, it is recommended to define the variable as a `Map` type rather than the specific type, as in the above example.
19+
This practice makes it easy to change the `Map` implementation later.
20+
~~~~
21+
22+
`HashMap` also has a copy constructor.
23+
24+
```java
25+
// Make a copy of a map
26+
Map<String, Integer> copy = new HashMap<>(fruitPrices);
27+
```
28+
29+
Add entries to the map using [put][map-put-javadoc].
30+
31+
```java
32+
fruitPrices.put("apple", 100);
33+
fruitPrices.put("pear", 80);
34+
// => { "apple" => 100, "pear" => 80 }
35+
```
36+
37+
Only one value can be associated with each key.
38+
Calling `put` with the same key will update the key's value.
39+
40+
```java
41+
fruitPrices.put("pear", 40);
42+
// => { "apple" => 100, "pear" => 40 }
43+
```
44+
45+
Use [get][map-get-javadoc] to get the value for a key.
46+
47+
```java
48+
fruitPrices.get("apple"); // => 100
49+
```
50+
51+
Use [containsKey][map-containskey-javadoc] to see if the map contains a particular key.
52+
53+
```java
54+
fruitPrices.containsKey("apple"); // => true
55+
fruitPrices.containsKey("orange"); // => false
56+
```
57+
58+
Remove entries with [remove][map-remove-javadoc].
59+
60+
```java
61+
fruitPrices.put("plum", 90); // Add plum to map
62+
fruitPrices.remove("plum"); // Removes plum from map
63+
```
64+
65+
The [size][map-size-javadoc] method returns the number of entries.
66+
67+
```java
68+
fruitPrices.size(); // Returns 2
69+
```
70+
71+
You can use the [keys] or [values] methods to obtain the keys or the values in a Map as a Set or collection respectively.
72+
73+
```java
74+
fruitPrices.keys(); // Returns "apple" and "pear" in a set
75+
fruitPrices.values(); // Returns 100 and 80, in a Collection
76+
```
77+
78+
## HashMap uses `hashCode` and `equals`
79+
80+
HashMaps uses the object's [hashCode][object-hashcode-javadoc] and [equals][object-equals-javadoc] method to work out where to store and how to retrieve the values for a key.
81+
For this reason, it is important that their return values do not change between storing and getting them, otherwise the HashMap may not be able to find the value.
82+
83+
For example, lets say we have the following class that will be used as the key to a map:
84+
85+
```java
86+
public class Stock {
87+
private String name;
88+
89+
public void setName(String name) {
90+
this.name = name;
91+
}
92+
93+
@Override
94+
public int hashCode() {
95+
return Objects.hash(name);
96+
}
97+
98+
@Override
99+
public boolean equals(Object obj) {
100+
if (obj == this) {
101+
return true;
102+
}
103+
if (Objects.equals(Stock.class, obj.getClass()) && obj instanceof Stock other) {
104+
return Objects.equals(name, other.name);
105+
}
106+
return false;
107+
}
108+
}
109+
```
110+
111+
The `hashCode` and `equals` depend on the `name` field, which can be changed via `setName`.
112+
Altering the `hashCode` can produce surprising results:
113+
114+
```java
115+
Stock stock = new Stock();
116+
stock.setName("Beanies");
117+
118+
Map<Stock, Integer> stockCount = new HashMap<>();
119+
stockCount.put(stock, 80);
120+
121+
stockCount.get(stock); // Returns 80
122+
123+
Stock other = new Stock();
124+
other.setName("Beanies");
125+
126+
stockCount.get(other); // Returns 80 because "other" and "stock" are equal
127+
128+
stock.setName("Choccies");
129+
stockCount.get(stock); // Returns null because hashCode value has changed
130+
131+
stockCount.get(other); // Also returns null because "other" and "stock" are not equal
132+
133+
stock.setName("Beanies");
134+
stockCount.get(stock); // HashCode restored, so returns 80 again
135+
136+
stockCount.get(other); // Also returns 80 again because "other" and "stock" are back to equal
137+
```
138+
139+
## Map.of and Map.copyOf
140+
141+
Another common way to create maps is to use [Map.of][map-of-javadoc] or [Map.ofEntries][map-ofentries-javadoc].
142+
143+
```java
144+
// Using Map.of
145+
Map<String, Integer> temperatures = Map.of("Mon", 30, "Tue", 28, "Wed", 32);
146+
147+
// or using Map.ofEntries
148+
Map<String, Integer> temperatures2 = Map.ofEntries(Map.entry("Mon", 30, "Tue", 28, "Wed", 32));
149+
```
150+
151+
Unlike `HashMap`, they populate the map upfront and become read-only once created.
152+
[Map.copyOf][map-copyof-javadoc] makes a read-only copy of a map.
153+
154+
```java
155+
Map<String, Integer> readOnlyFruitPrices = Map.copyOf(fruitPrices);
156+
```
157+
158+
Calling methods like `put`, `remove` or `clear` results in an `UnsupportedOperationException`.
159+
160+
[map-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html
161+
[hashmap-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/HashMap.html
162+
[map-put-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#put(K,V)
163+
[map-get-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#get(java.lang.Object)
164+
[map-containskey-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#containsKey(java.lang.Object)
165+
[map-remove-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#remove(java.lang.Object)
166+
[map-size-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#size()
167+
[map-of-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#of()
168+
[map-ofentries-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#ofEntries(java.util.Map.Entry...)
169+
[map-copyof-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#copyOf(java.util.Map)
170+
[object-hashcode-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Object.html#hashCode()
171+
[object-equals-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Object.html#equals(java.lang.Object)

concepts/maps/introduction.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Introduction
2+
3+
A **Map** is a data structure for storing key value pairs.
4+
It is similar to dictionaries in other programming languages.
5+
The [Map][map-javadoc] interface defines operations on a map.
6+
7+
Java has a number of different Map implementations.
8+
[HashMap][hashmap-javadoc] is a commonly used one.
9+
10+
```java
11+
// Make an instance
12+
Map<String, Integer> fruitPrices = new HashMap<>();
13+
```
14+
15+
Add entries to the map using [put][map-put-javadoc].
16+
17+
```java
18+
fruitPrices.put("apple", 100);
19+
fruitPrices.put("pear", 80);
20+
// => { "apple" => 100, "pear" => 80 }
21+
```
22+
23+
Only one value can be associated with each key.
24+
Calling `put` with the same key will update the key's value.
25+
26+
```java
27+
fruitPrices.put("pear", 40);
28+
// => { "apple" => 100, "pear" => 40 }
29+
```
30+
31+
Use [get][map-get-javadoc] to get the value for a key.
32+
33+
```java
34+
fruitPrices.get("apple"); // => 100
35+
```
36+
37+
Use [containsKey][map-containskey-javadoc] to see if the map contains a particular key.
38+
39+
```java
40+
fruitPrices.containsKey("apple"); // => true
41+
fruitPrices.containsKey("orange"); // => false
42+
```
43+
44+
Remove entries with [remove][map-remove-javadoc].
45+
46+
```java
47+
fruitPrices.put("plum", 90); // Add plum to map
48+
fruitPrices.remove("plum"); // Removes plum from map
49+
```
50+
51+
The [size][map-size-javadoc] method returns the number of entries.
52+
53+
```java
54+
fruitPrices.size(); // Returns 2
55+
```
56+
57+
You can use the [keys] or [values] methods to obtain the keys or the values in a Map as a Set or collection respectively.studentScores
58+
59+
```java
60+
fruitPrices.keys(); // Returns "apple" and "pear" in a set
61+
fruitPrices.values(); // Returns 100 and 80, in a Collection
62+
```
63+
64+
[map-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html
65+
[hashmap-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/HashMap.html
66+
[map-put-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#put(K,V)
67+
[map-get-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#get(java.lang.Object)
68+
[map-containskey-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#containsKey(java.lang.Object)
69+
[map-remove-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#remove(java.lang.Object)
70+
[map-size-javadoc]: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html#size()

concepts/maps/links.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[
2+
{
3+
"url": "https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Map.html",
4+
"description": "Interface Map documentation"
5+
},
6+
{
7+
"url": "https://dev.java/learn/api/collections-framework/maps/",
8+
"description": "Using Maps to Store Key Value Pairs"
9+
}
10+
]

config.json

+33-6
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,19 @@
308308
"generic-types"
309309
],
310310
"status": "beta"
311+
},
312+
{
313+
"slug": "international-calling-connoisseur",
314+
"name": "International Calling Connoisseur",
315+
"uuid": "03506c5a-601a-42cd-b037-c310208de84d",
316+
"concepts": [
317+
"maps"
318+
],
319+
"prerequisites": [
320+
"classes",
321+
"foreach-loops",
322+
"generic-types"
323+
]
311324
}
312325
],
313326
"practice": [
@@ -989,7 +1002,8 @@
9891002
"practices": [],
9901003
"prerequisites": [
9911004
"if-else-statements",
992-
"for-loops"
1005+
"for-loops",
1006+
"maps"
9931007
],
9941008
"difficulty": 5
9951009
},
@@ -1092,7 +1106,8 @@
10921106
"practices": [],
10931107
"prerequisites": [
10941108
"for-loops",
1095-
"arrays"
1109+
"arrays",
1110+
"maps"
10961111
],
10971112
"difficulty": 5
10981113
},
@@ -1144,7 +1159,8 @@
11441159
"practices": [],
11451160
"prerequisites": [
11461161
"chars",
1147-
"exceptions"
1162+
"exceptions",
1163+
"maps"
11481164
],
11491165
"difficulty": 6
11501166
},
@@ -1205,6 +1221,7 @@
12051221
"practices": [],
12061222
"prerequisites": [
12071223
"foreach-loops",
1224+
"maps",
12081225
"strings"
12091226
],
12101227
"difficulty": 6
@@ -1272,6 +1289,7 @@
12721289
"uuid": "38a405e8-619d-400f-b53c-2f06461fdf9d",
12731290
"practices": [],
12741291
"prerequisites": [
1292+
"maps",
12751293
"strings"
12761294
],
12771295
"difficulty": 6
@@ -1447,7 +1465,8 @@
14471465
"uuid": "2e760ae2-fadd-4d31-9639-c4554e2826e9",
14481466
"practices": [],
14491467
"prerequisites": [
1450-
"enums"
1468+
"enums",
1469+
"maps"
14511470
],
14521471
"difficulty": 7
14531472
},
@@ -1495,7 +1514,8 @@
14951514
"chars",
14961515
"if-else-statements",
14971516
"lists",
1498-
"for-loops"
1517+
"for-loops",
1518+
"maps"
14991519
],
15001520
"difficulty": 7
15011521
},
@@ -1556,7 +1576,8 @@
15561576
"prerequisites": [
15571577
"arrays",
15581578
"strings",
1559-
"if-else-statements"
1579+
"if-else-statements",
1580+
"maps"
15601581
],
15611582
"difficulty": 7
15621583
},
@@ -1703,6 +1724,7 @@
17031724
"exceptions",
17041725
"for-loops",
17051726
"if-else-statements",
1727+
"maps",
17061728
"numbers"
17071729
],
17081730
"difficulty": 8
@@ -1905,6 +1927,11 @@
19051927
"slug": "lists",
19061928
"name": "Lists"
19071929
},
1930+
{
1931+
"uuid": "2f6fdedb-a0ac-4bab-92d6-3be61520b9bc",
1932+
"slug": "maps",
1933+
"name": "Maps"
1934+
},
19081935
{
19091936
"uuid": "54118389-9c01-431b-a850-f47da498f845",
19101937
"slug": "method-overloading",

0 commit comments

Comments
 (0)