Skip to content

Commit 2168b21

Browse files
authored
Merge branch 'main' into 2555-new-concept-optional
2 parents 6db542e + 9ad48a7 commit 2168b21

File tree

21 files changed

+1154
-9
lines changed

21 files changed

+1154
-9
lines changed

POLICIES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ References: [[1](https://github.com/exercism/java/issues/177#issuecomment-261291
5151
> throw new UnsupportedOperationException("Delete this statement and write your own implementation.");
5252
> ```
5353
>
54-
> - Exercises of difficulty 5 or higher: copy the StubTemplate.java file (provided [here](https://github.com/exercism/java/tree/main/_template/src/main/java)) and rename it to fit the exercise. For example, for the exercise linked-list the file could be named LinkedList.java. Then either (1) add hints to the hints.md file (which gets merged into the README.md for the exercise) or (2) provide stubs as above for exercises that demand complicated method signatures.
54+
> - Exercises of difficulty 5 or higher: copy the StubTemplate.java file (provided [here](https://github.com/exercism/java/blob/main/resources/exercise-template/src/main/java/ExerciseName.java)) and rename it to fit the exercise. For example, for the exercise linked-list the file could be named LinkedList.java. Then either (1) add hints to the hints.md file (which gets merged into the README.md for the exercise) or (2) provide stubs as above for exercises that demand complicated method signatures.
5555
5656
References: [[1](https://github.com/exercism/java/issues/178)], [[2](https://github.com/exercism/java/pull/683#discussion_r125506930)], [[3](https://github.com/exercism/java/issues/977)], [[4](https://github.com/exercism/java/issues/1721)]
5757

concepts/maps/.meta/config.json

Lines changed: 7 additions & 0 deletions
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

Lines changed: 171 additions & 0 deletions
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

Lines changed: 70 additions & 0 deletions
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

Lines changed: 10 additions & 0 deletions
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

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,28 @@
313313
"slug": "tim-from-marketing-2",
314314
"name": "tim-from-marketing-2",
315315
"uuid": "a6cfc286-8c62-4f5b-8e59-f6bfc4374092",
316-
"concepts": [],
317-
"prerequisites": []
316+
"concepts": [
317+
"optional type"
318+
],
319+
"prerequisites": [
320+
"classes",
321+
"foreach-loops",
322+
"generic-types",
323+
"lists"
324+
]
325+
},
326+
{
327+
"slug": "international-calling-connoisseur",
328+
"name": "International Calling Connoisseur",
329+
"uuid": "03506c5a-601a-42cd-b037-c310208de84d",
330+
"concepts": [
331+
"maps"
332+
],
333+
"prerequisites": [
334+
"classes",
335+
"foreach-loops",
336+
"generic-types"
337+
]
318338
}
319339
],
320340
"practice": [
@@ -996,7 +1016,8 @@
9961016
"practices": [],
9971017
"prerequisites": [
9981018
"if-else-statements",
999-
"for-loops"
1019+
"for-loops",
1020+
"maps"
10001021
],
10011022
"difficulty": 5
10021023
},
@@ -1099,7 +1120,8 @@
10991120
"practices": [],
11001121
"prerequisites": [
11011122
"for-loops",
1102-
"arrays"
1123+
"arrays",
1124+
"maps"
11031125
],
11041126
"difficulty": 5
11051127
},
@@ -1151,7 +1173,8 @@
11511173
"practices": [],
11521174
"prerequisites": [
11531175
"chars",
1154-
"exceptions"
1176+
"exceptions",
1177+
"maps"
11551178
],
11561179
"difficulty": 6
11571180
},
@@ -1212,6 +1235,7 @@
12121235
"practices": [],
12131236
"prerequisites": [
12141237
"foreach-loops",
1238+
"maps",
12151239
"strings"
12161240
],
12171241
"difficulty": 6
@@ -1279,6 +1303,7 @@
12791303
"uuid": "38a405e8-619d-400f-b53c-2f06461fdf9d",
12801304
"practices": [],
12811305
"prerequisites": [
1306+
"maps",
12821307
"strings"
12831308
],
12841309
"difficulty": 6
@@ -1454,7 +1479,8 @@
14541479
"uuid": "2e760ae2-fadd-4d31-9639-c4554e2826e9",
14551480
"practices": [],
14561481
"prerequisites": [
1457-
"enums"
1482+
"enums",
1483+
"maps"
14581484
],
14591485
"difficulty": 7
14601486
},
@@ -1502,7 +1528,8 @@
15021528
"chars",
15031529
"if-else-statements",
15041530
"lists",
1505-
"for-loops"
1531+
"for-loops",
1532+
"maps"
15061533
],
15071534
"difficulty": 7
15081535
},
@@ -1563,7 +1590,8 @@
15631590
"prerequisites": [
15641591
"arrays",
15651592
"strings",
1566-
"if-else-statements"
1593+
"if-else-statements",
1594+
"maps"
15671595
],
15681596
"difficulty": 7
15691597
},
@@ -1710,6 +1738,7 @@
17101738
"exceptions",
17111739
"for-loops",
17121740
"if-else-statements",
1741+
"maps",
17131742
"numbers"
17141743
],
17151744
"difficulty": 8
@@ -1912,6 +1941,11 @@
19121941
"slug": "lists",
19131942
"name": "Lists"
19141943
},
1944+
{
1945+
"uuid": "2f6fdedb-a0ac-4bab-92d6-3be61520b9bc",
1946+
"slug": "maps",
1947+
"name": "Maps"
1948+
},
19151949
{
19161950
"uuid": "54118389-9c01-431b-a850-f47da498f845",
19171951
"slug": "method-overloading",

0 commit comments

Comments
 (0)