{"id":"lists-looping","slug":"looping-over-a-list","title":"Looping over a list","text":"To go through every value in a list, loop over the indexes, from 0 to the last one. With a `while` loop:\n\n```java\nArrayList<String> chores = new ArrayList<>();\nchores.add(\"sweep\");\nchores.add(\"dust\");\nchores.add(\"mop\");\n\nint index = 0;\nwhile (index < chores.size()) {\n    System.out.println(chores.get(index));\n    index++;\n}\n```\n\n```output\nsweep\ndust\nmop\n```\n\nA `for` loop does the same with the counter in one line, and it's the usual way to write it:\n\n```java\nArrayList<String> chores = new ArrayList<>();\nchores.add(\"sweep\");\nchores.add(\"dust\");\nchores.add(\"mop\");\n\nfor (int i = 0; i < chores.size(); i++) {\n    System.out.println((i + 1) + \". \" + chores.get(i));\n}\n```\n\n```output\n1. sweep\n2. dust\n3. mop\n```\n\n- The condition is `i < chores.size()`, with `<`, because the last index is `size() - 1`. With `<=`, the loop would ask for one index too many and crash.\n- With `size()` instead of a fixed number, the loop works for a list of any length. For an empty list it doesn't run at all.\n- `i` is the index, so `chores.get(i)` is this round's value, and `i + 1` its place as people count it.\n\n### Other ranges\n\nThe loop's three parts can pick any part of the list. Starting at 1 skips the first value, `i += 2` takes every second one, and starting at the last index and counting down goes through the list backwards:\n\n```java\nArrayList<Integer> numbers = new ArrayList<>();\nnumbers.add(10);\nnumbers.add(20);\nnumbers.add(30);\nnumbers.add(40);\nnumbers.add(50);\n\nfor (int i = 1; i < numbers.size(); i += 2) {\n    System.out.print(numbers.get(i) + \" \");\n}\nSystem.out.println();\n\nfor (int i = numbers.size() - 1; i >= 0; i--) {\n    System.out.print(numbers.get(i) + \" \");\n}\nSystem.out.println();\n```\n\n```output\n20 40\n50 40 30 20 10\n```\n\nGoing backwards, the loop starts at `size() - 1`, the last index, and runs as long as `i >= 0`, so index 0 is included.\n\nThe next module shows the for-each loop: a shorter way to visit every value, for when you don't need the index.\n","task":"Read names, one per line, until `end`. Then print them numbered, one per line, in the order they were read. For the input `Ada`, `Grace`, `Linus` and `end` the program prints:\n\n```\n1. Ada\n2. Grace\n3. Linus\n```\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> names = new ArrayList<>();\n\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> names = new ArrayList<>();\n        while (true) {\n            String name = scanner.nextLine();\n            if (name.equals(\"end\")) {\n                break;\n            }\n            names.add(name);\n        }\n        for (int i = 0; i < names.size(); i++) {\n            System.out.println((i + 1) + \". \" + names.get(i));\n        }\n    }\n}\n","hints":["First read all the names into the list. Then a second loop, `for (int i = 0; i < names.size(); i++)`, prints them.","The number in front is `i + 1`: put it in parentheses, `(i + 1) + \". \" + names.get(i)`."],"tests":[{"name":"Test 1","stdin":"Ada\nGrace\nLinus\nend\n","expect":"1. Ada\n2. Grace\n3. Linus","hidden":false},{"name":"Test 2","stdin":"Margaret\nend\n","expect":"1. Margaret","hidden":true},{"name":"Test 3","stdin":"Ken\nDennis\nBjarne\nJames\nGuido\nend\n","expect":"1. Ken\n2. Dennis\n3. Bjarne\n4. James\n5. Guido","hidden":true}],"require":[{"pattern":"\\bnames\\.size\\s*\\(\\s*\\)","message":"Loop over the list's indexes, up to `names.size()`."},{"pattern":"\\bnames\\.get\\s*\\(","message":"Print each name with `names.get(i)`."}],"forbid":[],"more":[{"task":"An editor keeps a history of your actions. Read the actions, one per line, until `end`. Then undo them all: print `Undo: ` and each action, starting from the last one and ending with the first. For the input `type`, `bold`, `paste` and `end` the program prints:\n\n```\nUndo: paste\nUndo: bold\nUndo: type\n```\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> actions = new ArrayList<>();\n\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> actions = new ArrayList<>();\n        while (true) {\n            String action = scanner.nextLine();\n            if (action.equals(\"end\")) {\n                break;\n            }\n            actions.add(action);\n        }\n        for (int i = actions.size() - 1; i >= 0; i--) {\n            System.out.println(\"Undo: \" + actions.get(i));\n        }\n    }\n}\n","hints":["Start the loop at the last index, `actions.size() - 1`, and count down with `i--`.","Keep going while `i >= 0`, so the action at index 0 is undone too."],"tests":[{"name":"Test 1","stdin":"type\nbold\npaste\nend\n","expect":"Undo: paste\nUndo: bold\nUndo: type","hidden":false},{"name":"Test 2","stdin":"delete\nend\n","expect":"Undo: delete","hidden":true},{"name":"Test 3","stdin":"type\ntype\nitalic\ncut\npaste\nend\n","expect":"Undo: paste\nUndo: cut\nUndo: italic\nUndo: type\nUndo: type","hidden":true}],"require":[{"pattern":"\\bactions\\.size\\s*\\(\\s*\\)","message":"Start from the last index, `actions.size() - 1`."},{"pattern":"\\bactions\\.get\\s*\\(","message":"Print each action with `actions.get(i)`."}],"forbid":[]},{"task":"What does this program print? Work out which indexes each loop visits.\n","kind":"predict","seed":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<String> letters = new ArrayList<>();\n        letters.add(\"a\");\n        letters.add(\"b\");\n        letters.add(\"c\");\n        letters.add(\"d\");\n        letters.add(\"e\");\n        letters.add(\"f\");\n        for (int i = 2; i < letters.size(); i += 3) {\n            System.out.println(letters.get(i));\n        }\n        for (int i = letters.size() - 2; i > 0; i -= 2) {\n            System.out.println(letters.get(i));\n        }\n    }\n}\n","solution":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<String> letters = new ArrayList<>();\n        letters.add(\"a\");\n        letters.add(\"b\");\n        letters.add(\"c\");\n        letters.add(\"d\");\n        letters.add(\"e\");\n        letters.add(\"f\");\n        for (int i = 2; i < letters.size(); i += 3) {\n            System.out.println(letters.get(i));\n        }\n        for (int i = letters.size() - 2; i > 0; i -= 2) {\n            System.out.println(letters.get(i));\n        }\n    }\n}\n","hints":["The list has 6 values, at indexes 0 to 5. The first loop visits indexes 2 and 5.","The second loop starts at index 4 and visits 4 and 2. At 0 the condition `i > 0` is false, so index 0 is left out."],"tests":[{"name":"Output","stdin":"","expect":"c\nf\ne\nc","hidden":false}],"require":[],"forbid":[],"lines":["c","f","e","c"]}]}