Java Arena
Step 4 of 5

var for local variables

Apart from lambda parameters (module 37), every variable in this course has had its type written in front of its name. Since Java 10, a local variable (one declared inside a method) can be declared with var instead, and javac works out its type from the value it's given:

var name = "Ada";
var age = 36;
var height = 1.65;
var languages = new ArrayList<String>();
languages.add("Java");
System.out.println(name.length() + age + " " + height + " " + languages);
Output
39 1.65 [Java]

name is a String, age an int, height a double and languages an ArrayList<String>, exactly as if the types were written out. var isn't a type of its own, and it doesn't make Java a language where a variable can hold anything: the type is decided once, when the variable is declared, and stays.

public class Main {
    public static void main(String[] args) {
        var count = 0;
        count = "many";
        System.out.println(count);
    }
}
What javac prints
Main.java:4: error: incompatible types: String cannot be converted to int
        count = "many";
                ^
1 error

Where var helps

var is at its best when the type is long and the right-hand side already shows it:

HashMap<String, ArrayList<Integer>> scores = new HashMap<String, ArrayList<Integer>>();
var scores = new HashMap<String, ArrayList<Integer>>();

Both lines declare the same variable; the second says the type once. Note that the type arguments move to the right: var scores = new HashMap<>(); would give javac nothing to work them out from, and it makes a HashMap<Object, Object>.

Where the right-hand side doesn't show the type, var makes code harder to read: in var result = calculate(data);, the reader has to look up calculate to know what result is. Many teams use var only when the type is plain to see.

Where var isn't allowed

javac must be able to work out the type from the declaration itself, so var needs a value right away, and null doesn't say which type is meant:

public class Main {
    public static void main(String[] args) {
        var total;
        var best = null;
        System.out.println("Done");
    }
}
What javac prints
Main.java:3: error: cannot infer type for local variable total
        var total;
            ^
  (cannot use 'var' on variable without initializer)
Main.java:4: error: cannot infer type for local variable best
        var best = null;
            ^
  (variable initializer is 'null')
2 errors

var is only for local variables (the loop variables of for included) and a lambda's parameters. Instance and static variables, method parameters and return types still need their types written out: javac answers a var there with "'var' is not allowed here".

var in loops, and a map's entries

A for-each loop's variable can be var too. That's handy for going through a map. So far, the course went through a map's keys with keySet() and looked up each value with get. A map's entrySet() gives its entries instead, each a key and its value together, with getKey() and getValue(). An entry's type is Map.Entry<String, Integer> here, a mouthful that var saves you from writing. A TreeMap, which module 31 mentioned, keeps its keys sorted, so the loop goes through them in alphabetical order:

import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        var stock = new TreeMap<String, Integer>();
        stock.put("water", 12);
        stock.put("apple", 4);
        stock.put("chips", 0);
        for (var entry : stock.entrySet()) {
            if (entry.getValue() == 0) {
                System.out.println(entry.getKey() + ": sold out");
            } else {
                System.out.println(entry.getKey() + ": " + entry.getValue());
            }
        }
    }
}
Output
apple: 4
chips: sold out
water: 12

Your task

Challenge 1 of 3

A dice tournament reads rolls, one per line as a player's name and the roll, such as Noor 5, until the line end, and prints each player's total, in the order the players first rolled. The program works, but its types make it wordy. Declare every local variable with var instead of its type: the ones inside the loops and the loops' own variables too. What it prints stays the same. With this input:

Input
Noor 5
Elif 6
Noor 3
Elif 6
end

the program prints:

Noor: 8
Elif: 12

Challenge 2

A dice game reads rolls, one per line as a name and the roll, such as Ada 4, until the line end, and prints the winner: the first player with the highest roll. Someone wrote it with var everywhere, and now it doesn't compile. Press Run to see javac's errors and fix each line it names, then run again: javac names more lines once the first ones are fixed. Keep going until the program works. With this input:

Input
Ada 4
Bo 6
Cy 6
end

the program prints:

Bo wins with 6

Challenge 3

A board game club checks its dice by counting how often each face comes up. The program reads rolls, one whole number per line, until the line end, and counts them in a TreeMap. Write the loop that prints each face that came up and its count, like 3: 2, smallest face first. Go through the map's entrySet() with a var loop variable. With this input:

Input
6
3
6
1
3
6
end

the program prints:

1: 1
3: 2
6: 3