WHAT YOU WILL MAKE
Make player scoreboard ScoreBoard
There is a new player in the server, and there is no need to add another variable to the scoreboard. Use names as keys to read out scores, and then use clear rules to handle missing points, deductions, sorting, and integer upper limits. Prerequisites: variables, methods, loops, ArrayList and generics. You don't have to create a player100Score when you let the 100th player join today.
Before you start: It is recommended to complete Lesson 25 first
- keyPlayer name, unique search identifier
- valueScore, repeatable
- entryA key-value mapping
01 / 14
Before starting: predict first, then let the program answer
This chapter uses JDK 21 and does not require the preview function. The story is borrowed from the block world, and the example runs on the ordinary Java console; if the values and rules are course models, they will be clearly stated.
Each common example is a complete independent file, saved according to the file name marked on the box. Place each example in a different folder to avoid duplicate names of auxiliary classes. When the complete project is divided into sections, they are connected sequentially in the same file.
Terminal command: replace the Chinese placeholder with the actual file name and class name
javac -encoding UTF-8 ExampleFile.java
java ExampleClass- Prediction: Write the expected output first, or draw out the changes in references and data.
- Verification: Check line by line after running, and then only change one condition.
- Explanation: Explain whether the results come from Java rules, course contracts, or input data.
02 / 14
keys and values form a lookup table
Map is like a server scoreboard. The player name is the key and the score is the value; the program quickly finds the corresponding score through the name.
Only one copy of the current value is retained for the same key. Two different players can have exactly the same score.
- keyPlayer name, unique search identifier
- valueScore, repeatable
- entryA key-value mapping
| Concept | Scoreboard Example | Rules |
|---|---|---|
| key key | Player name Alex | Unique in the same Map |
| value value | Score 12 | Duplication allowed |
| Mapping entry | Alex corresponds to 12 | A set of keys and values |
03 / 14
Create HashMap and put data
Write the key and value types when declaring. String, Integer in angle brackets means that only string keys and integer values can be used.
- Map<String,Integer>Clear key value type
- putThe key with the same name replaces the old value
- sizeCurrent record number
L26Example02.java · Complete independent example
import java.util.*;
public class L26Example02 {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>();
scores.put("Alex", 12); scores.put("Steve", 12);
scores.put("Alex", 20);
System.out.println(scores.get("Alex"));
System.out.println(scores.size());
}
}Output
20
2BadMapType.java · Intentional error example
import java.util.*;
public class BadMapType {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>();
scores.put("Alex", "12");
}
}04 / 14
Safety cumulative score
A put with the same name will replace the old value without increasing the number of records. The get of the new key returns null, and direct unboxing and addition will fail. Let's look at simple counting first, and then establish clear contracts for large numbers, null and illegal old records.
- does not existgetOrDefault gives default 0
- null already existsThe default value does not replace it
- Safe additionConvert large numbers to long first and check
L26Example03.java · Complete independent example
import java.util.*;
public class L26Example03 {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>();
scores.put("Alex", scores.getOrDefault("Alex", 0) + 5);
scores.merge("Alex", 3, Integer::sum);
System.out.println(scores.get("Alex"));
}
}Output
805 / 14
Non-existing keys must be handled explicitly
get returns null for a non-existent key. The scoreboard can choose to display 0, or it can explicitly tell the user that the player cannot be found.
- getReturn null for missing key
- containsKeyDetermine whether the key exists
- 0 point playerPresence and absence are different
L26Example04.java · Complete independent example
import java.util.*;
public class L26Example04 {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>();
scores.put("Alex", 0);
System.out.println(scores.get("Mia"));
System.out.println(scores.getOrDefault("Mia", 0));
System.out.println(scores.containsKey("Alex"));
System.out.println(scores.containsKey("Mia"));
}
}Output
null
0
true
false06 / 14
entrySet gets the key and value at once
Just traversing keySet and then calling get can also work, but entrySet directly provides complete records, which makes the expression clearer.
- entrySetGet the key and value at the same time
- HashMapNo commitment to traversal order
- TreeMap copyKey generation stable display
L26Example05.java · Complete independent example
import java.util.*;
public class L26Example05 {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>(Map.of("Steve", 8, "Alex", 12));
for (var entry : new TreeMap<>(scores).entrySet())
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}Output
Alex=12
Steve=807 / 14
Delete players and understand the order
remove(key) deletes the entire record and returns the old value; returns null when the key does not exist. clear() will clear the entire table.
- remove(key)Delete and return the old value
- clear()Clear all records
- Display orderNeed to clearly choose to implement
L26Example06.java · Complete independent example
import java.util.*;
public class L26Example06 {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>(Map.of("Alex", 12));
System.out.println(scores.remove("Alex"));
System.out.println(scores.remove("Alex"));
scores.clear();
System.out.println(scores.size());
}
}Output
12
null
008 / 14
Method parameters are oriented to Map contract
If the method only requires the general operation of Map, the parameters should be written as Map<K,V> instead of being locked as HashMap.
- Name checkReject empty names, remove leading and trailing blanks
- long calculationPrevent int addition from overflowing
- Last updatedData remains unchanged when rejected
L26Example07.java · Complete independent example
import java.util.*;
public class L26Example07 {
static boolean addScore(Map<String, Integer> scores,
String player, int delta) {
if (scores == null || player == null || player.isBlank()) return false;
String key = player.strip();
Integer old = scores.get(key);
if (scores.containsKey(key) && (old == null || old < 0)) return false;
int current = old == null ? 0 : old;
long next = (long) current + delta;
if (next > Integer.MAX_VALUE) return false;
scores.put(key, (int) Math.max(0L, next));
return true;
}
static int getScore(Map<String, Integer> scores, String player) {
if (scores == null || player == null || player.isBlank()) return 0;
String key = player.strip();
Integer value = scores.get(key);
if (!scores.containsKey(key)) return 0;
if (value == null || value < 0)
throw new IllegalStateException("Scoring record corrupted: " + key);
return value;
}
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>();
System.out.println(addScore(scores, " Alex ", 5));
System.out.println(addScore(scores, "Alex", -20));
System.out.println(getScore(scores, "Alex"));
scores.put("Alex", Integer.MAX_VALUE);
System.out.println(addScore(scores, "Alex", 1));
System.out.println(getScore(scores, "Alex"));
}
}Output
true
true
0
false
214748364709 / 14
Ranking list is copied first and then sorted
HashMap is suitable for checking scores by name, but is not suitable for expressing the first and second places. When making a ranking list, copy the records to the list and then sort them.
- Map.entryCopy unmodifiable value entries
- In descending order of scoresDetermine ranking
- Same score by nameOutput is repeatable
L26Example08.java · Complete independent example
import java.util.*;
public class L26Example08 {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>(Map.of("Steve", 8, "Alex", 8));
List<Map.Entry<String, Integer>> ranking = new ArrayList<>();
scores.forEach((name, score) -> ranking.add(Map.entry(name, score)));
ranking.sort(Map.Entry.<String, Integer>comparingByValue().reversed()
.thenComparing(Map.Entry.comparingByKey()));
scores.put("Alex", 99);
for (var entry : ranking)
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}Output
Alex=8
Steve=810 / 14
Three types of tests keep scoreboard
When testing the extra points method, don't just look at one line of output. Also check if the failed operation secretly changed the Map.
- Normal bonus pointsOld value increased
- Minimum 0 pointsPoint deduction clamping
- Failed CheckEqual to snapshot before operation
| Scene | Operation | Expected |
|---|---|---|
| Normal | Alex plus 5 | Score increased by 5 |
| Border | Players with 0 points will be deducted 1 | Still 0 |
| Error | Add 5 to empty name | Return false and the data remains unchanged |
| Error | null Map | Return false without throwing an exception |
| Query | No player exists | Return 0 |
L26Example09.java · Complete independent example
import java.util.*;
public class L26Example09 {
static boolean addScore(Map<String, Integer> scores,
String player, int delta) {
if (scores == null || player == null || player.isBlank()) return false;
String key = player.strip();
Integer old = scores.get(key);
if (scores.containsKey(key) && (old == null || old < 0)) return false;
int current = old == null ? 0 : old;
long next = (long) current + delta;
if (next > Integer.MAX_VALUE) return false;
scores.put(key, (int) Math.max(0L, next));
return true;
}
static int getScore(Map<String, Integer> scores, String player) {
if (scores == null || player == null || player.isBlank()) return 0;
String key = player.strip();
Integer value = scores.get(key);
if (!scores.containsKey(key)) return 0;
if (value == null || value < 0)
throw new IllegalStateException("Scoring record corrupted: " + key);
return value;
}
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>(Map.of("Alex", 12));
Map<String, Integer> before = new HashMap<>(scores);
boolean ok = addScore(scores, " ", 5);
System.out.println(!ok && scores.equals(before));
System.out.println(getScore(scores, "Mia"));
}
}Output
true
011 / 14
Challenge Blueprint Player Scoreboard
The challenge program is called ScoreBoard. It should support addition and subtraction of points for new players and old players, safe query and deletion, while not relying on the traversal order of HashMap.
- Add playerStart from 0 when it does not exist
- Query missingThis lesson returns 0
- Delete playerMapping completely removed
Acceptance sequence
- Alex adds 5 from 12, and the query results in 17.
- Steve deducted 20 from 8, and the lowest score was clamped to 0.
- Querying missing Mia returns 0, but containsKey is identifiable as missing.
- An empty name operation returns false and the scoreboard remains unchanged.
- Deleting Steve returns the old score of 0, leaving only 1 player.
12 / 14
Scoreboard Program
Create a new ScoreBoard.java, compile and run using Java 21.
- AlexAdd 12 to 5 to get 17
- Steve8 buckle 20 to get 0
- Delete SteveLast 1 player left
ScoreBoard.java · Complete standalone example
import java.util.*;
public class ScoreBoard {
static boolean addScore(Map<String, Integer> scores,
String player, int delta) {
if (scores == null || player == null || player.isBlank()) return false;
String key = player.strip();
Integer old = scores.get(key);
if (scores.containsKey(key) && (old == null || old < 0)) return false;
int current = old == null ? 0 : old;
long next = (long) current + delta;
if (next > Integer.MAX_VALUE) return false;
scores.put(key, (int) Math.max(0L, next));
return true;
}
static int getScore(Map<String, Integer> scores, String player) {
if (scores == null || player == null || player.isBlank()) return 0;
String key = player.strip();
Integer value = scores.get(key);
if (!scores.containsKey(key)) return 0;
if (value == null || value < 0)
throw new IllegalStateException("Scoring record corrupted: " + key);
return value;
}
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>();
addScore(scores, "Alex", 12); addScore(scores, "Steve", 8);
addScore(scores, "Alex", 5); addScore(scores, "Steve", -20);
System.out.println("Alex=" + getScore(scores, "Alex"));
System.out.println("Steve=" + getScore(scores, "Steve"));
System.out.println("Mia=" + getScore(scores, "Mia"));
System.out.println("Empty name=" + addScore(scores, " ", 5));
System.out.println("Delete=" + scores.remove("Steve"));
System.out.println("Number of players=" + scores.size());
}
}Output
Alex=17
Steve=0
Mia=0
Empty name=false
Delete=0
Number of players=113 / 14
Expansion tasks and clearance review
The job submits code, test table and a fault record at the same time. Explain why a certain field was chosen as a key.
- Select keyExplain the search purpose
- Definition failedMissing, empty name, overflow
- Verification sequenceCannot rely on HashMap order
Third gear operation
- Wooden pickaxe: Create an item price list and support new additions, price changes and inquiries.
- Iron pickaxe: Count the number of occurrences of a group of dropped objects.
- Diamond Pickaxe: Copy the scoring records to the list and output the top three with the highest scores.
| Self-evaluation | Can | Still need to practice |
|---|---|---|
| I can design keys and values | □ | □ |
| I can safely query for missing keys | □ | □ |
| I don't rely on HashMap order | □ | □ |
14 / 14
Own acceptance record
Beautiful output is the starting point, and being able to explain boundaries is considered mastery. Select one case each from normal, borderline and error, write down your expectations before running, and leave evidence after running.
| Category | The operation you selected | Check key points |
|---|---|---|
| Normal | A common input or a successful action | Is the result consistent line by line? |
| Border | Range endpoints and adjacent values | Is there one more step or one less thing? |
| Error | Illegal quantity, missing object or bad data | Whether it is explicitly rejected and whether the status is maintained |
- Bug records: triggering conditions, actual phenomena, causes, and minimum repairs.
- Illustrated record: describe the starting point, end point and meaning of each arrow.
- Adaptation record: only change one rule, and modify expectations and tests at the same time.
TAKE IT WITH YOU
Take the lesson offline
The complete lesson, code, diagrams and exercises, in your preferred language.