Checkpoint: Java Basics

You've learned data types, type casting, Scanner input, the Math class, StringBuilder, ArrayList and HashMap — let's combine them. In this checkpoint you'll build one small but complete program that reads input, tallies it with a HashMap, and prints a formatted report.

Learn Checkpoint: Java Basics in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

8 primitives, their ranges, overflow, and why double is wrong for money.

Widening is automatic, narrowing needs (type) , casts truncate, and parsing turns text into numbers.

nextLine / next / nextInt / nextDouble , the newline trap, and hasNextInt validation.

abs , max / min , pow , sqrt , rounding, and random numbers.

Efficient text building and printf / String.format specifiers.

Resizable lists, key→value maps, iteration, and the tally pattern.

Write a program that reads spending entries and prints a per-category report. Each entry is a category word followed by an amount, for example food 12.50 . Reading stops when the user types done .

Start from this scaffold — fill in the TODOs, then run it. Try it yourself before revealing the solution!

Give it a real attempt first. When you're ready, expand the full solution and walk through how each skill from this section fits together.

Test yourself across the whole section. Try to answer before expanding each one.

1. Why does the tally use HashMap<String, Double> rather than HashMap<String, double> ?

Collections store objects, not primitives, so the value type must be the wrapper class Double . Autoboxing converts between double and Double automatically.

2. What does (int) 19.99 evaluate to, and how would you instead get 20?

19 — casting truncates, it doesn't round. To get 20 use Math.round(19.99) (which returns a long ), then cast to int if needed.

3. After int n = scanner.nextInt(); the next scanner.nextLine() returns an empty string. Why, and what's the fix?

nextInt() leaves the trailing newline in the buffer, which the next nextLine() consumes immediately. Fix it by adding an extra scanner.nextLine(); after the numeric read.

4. With an ArrayList<Integer> holding [10, 20, 30], what does list.remove(1) leave, and why is this a famous trap?

[10, 30] . remove(1) deletes the element at index 1 (the value 20). To remove the value 1 you'd write remove(Integer.valueOf(1)) .

5. Why prefer StringBuilder over + when assembling a long report in a loop?

Strings are immutable, so each + creates a new String object; in a large loop that's quadratic work. StringBuilder.append writes into one growable buffer, so it stays linear.

6. What does map.getOrDefault("x", 0) return when "x" is not in the map, and why is that useful for counting?

It returns 0 instead of null . That lets the tally pattern add 1 to a not-yet-seen key without a NullPointerException or a special first-time check.

You combined data types, casting, Scanner input, validation, the HashMap tally pattern, and printf formatting into one complete program. That's a real, useful skill — the same loop-read-tally-report shape powers countless tools.

Next up: Switch Statement & Switch Expressions — a cleaner way to branch on many values than long if/else chains.

Practice quiz

Why must a map be HashMap<String, Double> rather than HashMap<String, double>?

  • double is faster
  • double is not a real type
  • Collections store objects, not primitives, so the value must be the wrapper Double
  • Generics forbid all numbers

Answer: Collections store objects, not primitives, so the value must be the wrapper Double. Generic type arguments must be reference types. Autoboxing converts between double and Double automatically.

What does (int) 19.99 evaluate to?

  • 19
  • 20
  • 19.99
  • Compile error

Answer: 19. Casting a double to int truncates toward zero — it does not round. (int)19.99 is 19; use Math.round to get 20.

After int n = scanner.nextInt();, the next scanner.nextLine() often returns an empty string. Why?

  • nextInt() consumes the whole line
  • nextLine() is broken
  • The buffer is cleared automatically
  • nextInt() leaves the trailing newline, which nextLine() then consumes

Answer: nextInt() leaves the trailing newline, which nextLine() then consumes. nextInt() reads the number but leaves the newline in the buffer. Add an extra scanner.nextLine() to skip it.

With an ArrayList<Integer> holding [10, 20, 30], what does list.remove(1) leave?

remove(int) deletes by INDEX, so remove(1) removes the value 20, leaving [10, 30].

To remove the VALUE 1 (not index 1) from an ArrayList<Integer>, you call:

  • list.remove(Integer.valueOf(1))
  • list.remove(1)
  • list.delete(1)
  • list.removeValue(1)

Answer: list.remove(Integer.valueOf(1)). remove(int) is by index; remove(Object) is by value. Integer.valueOf(1) forces the by-value overload.

Why prefer StringBuilder over + when assembling a long report in a loop?

  • + does not compile in loops
  • StringBuilder rounds numbers
  • Strings are immutable, so each + creates a new object (quadratic work); StringBuilder uses one buffer
  • There is no difference

Answer: Strings are immutable, so each + creates a new object (quadratic work); StringBuilder uses one buffer. Each + builds a new String. StringBuilder.append writes into one growable buffer, keeping the work linear.

What does map.getOrDefault("x", 0) return when "x" is not in the map?

  • null
  • 0
  • -1
  • Throws NullPointerException

Answer: 0. It returns the supplied default (0) instead of null, enabling the tally pattern without a null check.

Which printf specifier correctly prints a double amount to 2 decimal places?

  • %d
  • %s
  • %2d
  • %.2f

Answer: %.2f. %.2f formats a floating-point value to two decimals. %d with a double throws an exception.

How should you compare a Scanner-read String token to the sentinel "done"?

  • category == "done"
  • category.equals("done")
  • category = "done"
  • category.compareTo("done")

Answer: category.equals("done"). Use .equals for String content; == compares references and can be false even for equal text.

The tally line totals.put(cat, totals.getOrDefault(cat, 0.0) + amount) works because getOrDefault:

  • Deletes the key first
  • Throws if the key is missing
  • Returns 0.0 for an unseen category so the first amount adds to zero
  • Always returns the amount

Answer: Returns 0.0 for an unseen category so the first amount adds to zero. For a new category it returns 0.0, so the first amount starts the total; later amounts accumulate.