{"id":"lists-index-errors","slug":"index-out-of-bounds","title":"When the index doesn't exist","text":"A list with three values has the indexes 0, 1 and 2, and no others. Asking for any other index stops the program with an error:\n\n```java\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<String> chores = new ArrayList<>();\n        chores.add(\"do the dishes\");\n        chores.add(\"water the plants\");\n        chores.add(\"take out the trash\");\n        System.out.println(chores.get(0));\n        System.out.println(chores.get(3));\n        System.out.println(\"All done\");\n    }\n}\n```\n\n```output\ndo the dishes\n```\n\n```crash\nException in thread \"main\" java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3\n\tat Main.main(Main.java:10)\n```\n\nThe program compiled without a complaint: javac can't know how many values a list will hold when the program runs. The error comes while it runs, as an **exception**, and the program stops on the spot. That's why `All done` is never printed. Java's message says what went wrong and where:\n\n- `IndexOutOfBoundsException` is the kind of error: an index outside the list.\n- `Index 3 out of bounds for length 3` gives the index that was asked for, and how many values the list had.\n- `at Main.main(Main.java:10)` is where it happened: line 10, in the method `main`.\n\nIn a real run, Java also prints a few `at` lines from inside its own classes, where the index was checked. The one to look for is the `at Main` line: that's your code.\n\nA negative index crashes the same way (`Index -1 out of bounds for length 3`), and so does every index on an empty list (`Index 0 out of bounds for length 0`).\n\n### Avoiding it\n\nThe largest index is always one less than the number of values. A common cause of this crash is counting from 1, as people do, instead of from 0: `get(3)` for the third value, or a loop that runs one round too far. When the index in the message equals the length, as in `Index 3 out of bounds for length 3`, look for exactly that mistake.\n\nThe next step shows how to ask a list how many values it holds, so a program can check an index before it uses it.\n","task":"This program crashes. Run it, read the message, and fix the mistake, so the program prints:\n\n```\nFirst stop: Station\nSecond stop: Library\nLast stop: Harbor\n```\n","kind":"code","seed":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<String> stops = new ArrayList<>();\n        stops.add(\"Station\");\n        stops.add(\"Library\");\n        stops.add(\"Harbor\");\n        System.out.println(\"First stop: \" + stops.get(1));\n        System.out.println(\"Second stop: \" + stops.get(2));\n        System.out.println(\"Last stop: \" + stops.get(3));\n    }\n}\n","solution":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<String> stops = new ArrayList<>();\n        stops.add(\"Station\");\n        stops.add(\"Library\");\n        stops.add(\"Harbor\");\n        System.out.println(\"First stop: \" + stops.get(0));\n        System.out.println(\"Second stop: \" + stops.get(1));\n        System.out.println(\"Last stop: \" + stops.get(2));\n    }\n}\n","hints":["The message says index 3, for a list of length 3: its indexes only go up to 2.","All three indexes are one too big. The first stop is at index 0."],"tests":[{"name":"The program","stdin":"","expect":"First stop: Station\nSecond stop: Library\nLast stop: Harbor","hidden":false}],"require":[{"pattern":"\\bstops\\.get\\s*\\(","min":3,"message":"Keep getting each stop from the list with `stops.get(...)`."}],"forbid":[],"more":[{"task":"The cafeteria's menu has a dish for each index from 0 to 4. The program reads an index and prints that dish, but it crashes for an index outside the menu. Add a check: for an index from 0 to 4, print the dish as before; for any other index, print `No dish at index` and the index. For the input `7` the program prints:\n\n```\nNo dish at index 7\n```\n\nFor the input `2` it prints `Dish: curry`.\n","kind":"code","seed":"import java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        ArrayList<String> menu = new ArrayList<>();\n        menu.add(\"soup\");\n        menu.add(\"pasta\");\n        menu.add(\"curry\");\n        menu.add(\"tacos\");\n        menu.add(\"salad\");\n        int index = Integer.valueOf(scanner.nextLine());\n        System.out.println(\"Dish: \" + menu.get(index));\n    }\n}\n","solution":"import java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        ArrayList<String> menu = new ArrayList<>();\n        menu.add(\"soup\");\n        menu.add(\"pasta\");\n        menu.add(\"curry\");\n        menu.add(\"tacos\");\n        menu.add(\"salad\");\n        int index = Integer.valueOf(scanner.nextLine());\n        if (index >= 0 && index <= 4) {\n            System.out.println(\"Dish: \" + menu.get(index));\n        } else {\n            System.out.println(\"No dish at index \" + index);\n        }\n    }\n}\n","hints":["An index works when it's at least 0 and at most 4: `index >= 0 && index <= 4`.","Put the `get` line inside the `if`, and the `No dish` line in the `else`."],"tests":[{"name":"Test 1","stdin":"7\n","expect":"No dish at index 7","hidden":false},{"name":"Test 2","stdin":"2\n","expect":"Dish: curry","hidden":false},{"name":"Test 3","stdin":"0\n","expect":"Dish: soup","hidden":true},{"name":"Test 4","stdin":"4\n","expect":"Dish: salad","hidden":true},{"name":"Test 5","stdin":"5\n","expect":"No dish at index 5","hidden":true},{"name":"Test 6","stdin":"-1\n","expect":"No dish at index -1","hidden":true}],"require":[{"pattern":"\\bmenu\\.get\\s*\\(\\s*index\\s*\\)","message":"Keep printing the dish with `menu.get(index)`."}],"forbid":[]},{"task":"This program prints four lap times and then crashes before `Race over`. Read the message to find the cause, and fix it, so the program prints:\n\n```\nLap 1: 62 s\nLap 2: 58 s\nLap 3: 60 s\nLap 4: 57 s\nRace over\n```\n","kind":"code","seed":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> laps = new ArrayList<>();\n        laps.add(62);\n        laps.add(58);\n        laps.add(60);\n        laps.add(57);\n        for (int i = 0; i <= 4; i++) {\n            System.out.println(\"Lap \" + (i + 1) + \": \" + laps.get(i) + \" s\");\n        }\n        System.out.println(\"Race over\");\n    }\n}\n","solution":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> laps = new ArrayList<>();\n        laps.add(62);\n        laps.add(58);\n        laps.add(60);\n        laps.add(57);\n        for (int i = 0; i < 4; i++) {\n            System.out.println(\"Lap \" + (i + 1) + \": \" + laps.get(i) + \" s\");\n        }\n        System.out.println(\"Race over\");\n    }\n}\n","hints":["The message says `Index 4 out of bounds for length 4`: in its last round, the loop asks for index 4, one past the end.","The loop must stop after index 3: `i < 4` instead of `i <= 4`."],"tests":[{"name":"The program","stdin":"","expect":"Lap 1: 62 s\nLap 2: 58 s\nLap 3: 60 s\nLap 4: 57 s\nRace over","hidden":false}],"require":[{"pattern":"\\bfor\\s*\\(","message":"Keep the loop."},{"pattern":"\\blaps\\.get\\s*\\(\\s*i\\s*\\)","message":"Keep getting each lap time with `laps.get(i)`."}],"forbid":[]}]}