{"id":"list-methods-references","slug":"same-list-two-names","title":"One list, two names","text":"Module 10 showed that a method gets a copy of an `int` argument, so changing the parameter doesn't change the caller's variable. Lists behave differently, and here's why.\n\nA list variable doesn't hold the list's values. It holds a **reference**: a note of where the list is in the computer's memory. `new ArrayList<>()` makes the list, and the variable remembers where it is. Copying the variable copies the note, not the list:\n\n```java\nArrayList<String> mine = new ArrayList<>();\nmine.add(\"tea\");\nArrayList<String> yours = mine;\nyours.add(\"coffee\");\nSystem.out.println(mine);\nSystem.out.println(yours);\n```\n\n```output\n[tea, coffee]\n[tea, coffee]\n```\n\nThere's only one list here, with two names. Adding through `yours` changes the list `mine` refers to, because it's the same list.\n\n### A method can change the caller's list\n\nA list parameter works the same way. The method gets a copy of the reference, and it leads to the caller's own list. Whatever the method does to that list, the caller sees:\n\n```java\nimport java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> prices = new ArrayList<>();\n        prices.add(10);\n        prices.add(25);\n        raiseAll(prices, 2);\n        System.out.println(prices);\n    }\n\n    public static void raiseAll(ArrayList<Integer> list, int amount) {\n        for (int i = 0; i < list.size(); i++) {\n            list.set(i, list.get(i) + amount);\n        }\n    }\n}\n```\n\n```output\n[12, 27]\n```\n\n`list.set(index, value)` puts a new value at an index, in place of the old one. `raiseAll` returns nothing, and still `main`'s list changed. That's handy when changing the list is the method's job. When it isn't, it's a nasty surprise, so a method that only needs to read a list (like `groupPrice` in the last step) should leave it alone.\n\n### A real copy\n\nFor a second, separate list, make a new list from the old one: `new ArrayList<>(original)` creates a new list with the same values in the same order.\n\n```java\nArrayList<String> original = new ArrayList<>();\noriginal.add(\"tea\");\nArrayList<String> copy = new ArrayList<>(original);\ncopy.add(\"coffee\");\nSystem.out.println(original);\nSystem.out.println(copy);\n```\n\n```output\n[tea]\n[tea, coffee]\n```\n\nNow there are two lists, and changing one leaves the other as it was.\n","task":"What does this program print? Count how many lists there really are.\n","kind":"predict","seed":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<String> plan = new ArrayList<>();\n        plan.add(\"swim\");\n        plan.add(\"run\");\n        ArrayList<String> other = plan;\n        ArrayList<String> backup = new ArrayList<>(plan);\n        other.add(\"bike\");\n        backup.remove(0);\n        System.out.println(plan);\n        System.out.println(other);\n        System.out.println(backup);\n    }\n}\n","solution":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<String> plan = new ArrayList<>();\n        plan.add(\"swim\");\n        plan.add(\"run\");\n        ArrayList<String> other = plan;\n        ArrayList<String> backup = new ArrayList<>(plan);\n        other.add(\"bike\");\n        backup.remove(0);\n        System.out.println(plan);\n        System.out.println(other);\n        System.out.println(backup);\n    }\n}\n","hints":["`other = plan` gives the one list a second name. `new ArrayList<>(plan)` makes a separate list with `swim` and `run`.","Adding `bike` through `other` changes `plan` too. Removing index 0 from `backup` changes only the copy."],"tests":[{"name":"Output","stdin":"","expect":"[swim, run, bike]\n[swim, run, bike]\n[run]","hidden":false}],"require":[],"forbid":[],"lines":["[swim, run, bike]","[swim, run, bike]","[run]"],"more":[{"task":"Write a method `capAt(ArrayList<Integer> levels, int max)` that changes the list itself: every value above `max` becomes `max`. It returns nothing. The check builds a list of 40, 120, 75 and 101, calls `capAt(levels, 100);`, and then prints the list:\n\n```\n[40, 100, 75, 100]\n```\n","kind":"code","seed":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> levels = new ArrayList<>();\n        levels.add(40);\n        levels.add(120);\n        levels.add(75);\n        levels.add(101);\n        capAt(levels, 100);\n        System.out.println(levels);\n    }\n\n    // Write the capAt method here.\n}\n","solution":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> levels = new ArrayList<>();\n        levels.add(40);\n        levels.add(120);\n        levels.add(75);\n        levels.add(101);\n        capAt(levels, 100);\n        System.out.println(levels);\n    }\n\n    public static void capAt(ArrayList<Integer> levels, int max) {\n        for (int i = 0; i < levels.size(); i++) {\n            if (levels.get(i) > max) {\n                levels.set(i, max);\n            }\n        }\n    }\n}\n","hints":["The method is `void`: it changes the caller's list, so there's nothing to return.","An index loop, and inside it `if (levels.get(i) > max) { levels.set(i, max); }`."],"tests":[{"name":"Test 1","stdin":"","call":"ArrayList<Integer> levels = new ArrayList<>();\nlevels.add(40);\nlevels.add(120);\nlevels.add(75);\nlevels.add(101);\ncapAt(levels, 100);\nSystem.out.println(levels);\n","expect":"[40, 100, 75, 100]","hidden":false},{"name":"Test 2","stdin":"","call":"ArrayList<Integer> levels = new ArrayList<>();\nlevels.add(5);\ncapAt(levels, 10);\nSystem.out.println(levels);\n","expect":"[5]","hidden":true},{"name":"Test 3","stdin":"","call":"ArrayList<Integer> levels = new ArrayList<>();\nlevels.add(3);\nlevels.add(0);\nlevels.add(8);\nlevels.add(-2);\ncapAt(levels, 0);\nSystem.out.println(levels);\n","expect":"[0, 0, 0, -2]","hidden":true}],"require":[{"pattern":"\\.set\\s*\\(","message":"Replace a value in the list with `set(index, value)`."}],"forbid":[]},{"task":"The program reads scores until the line `end`, keeps the list as it was in `before`, and then doubles every score. But `Before:` shows the doubled scores too. Fix the line that makes `before`, so it holds a real copy. For the input 3, 5 and 8 the program prints:\n\n```\nBefore: [3, 5, 8]\nAfter: [6, 10, 16]\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<Integer> scores = new ArrayList<>();\n        while (true) {\n            String line = scanner.nextLine();\n            if (line.equals(\"end\")) {\n                break;\n            }\n            scores.add(Integer.valueOf(line));\n        }\n\n        ArrayList<Integer> before = scores;\n        for (int i = 0; i < scores.size(); i++) {\n            scores.set(i, scores.get(i) * 2);\n        }\n        System.out.println(\"Before: \" + before);\n        System.out.println(\"After: \" + scores);\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<Integer> scores = new ArrayList<>();\n        while (true) {\n            String line = scanner.nextLine();\n            if (line.equals(\"end\")) {\n                break;\n            }\n            scores.add(Integer.valueOf(line));\n        }\n\n        ArrayList<Integer> before = new ArrayList<>(scores);\n        for (int i = 0; i < scores.size(); i++) {\n            scores.set(i, scores.get(i) * 2);\n        }\n        System.out.println(\"Before: \" + before);\n        System.out.println(\"After: \" + scores);\n    }\n}\n","hints":["`before = scores` gives the same list a second name, so doubling the scores shows up through both names.","Make a new list with the same values: `ArrayList<Integer> before = new ArrayList<>(scores);`"],"tests":[{"name":"Test 1","stdin":"3\n5\n8\nend\n","expect":"Before: [3, 5, 8]\nAfter: [6, 10, 16]","hidden":false},{"name":"Test 2","stdin":"10\nend\n","expect":"Before: [10]\nAfter: [20]","hidden":true},{"name":"Test 3","stdin":"-4\n0\n7\n1\nend\n","expect":"Before: [-4, 0, 7, 1]\nAfter: [-8, 0, 14, 2]","hidden":true}],"require":[{"pattern":"new\\s+ArrayList\\s*<[^>]*>\\s*\\(\\s*scores\\s*\\)","message":"Make `before` a copy of the list: `new ArrayList<>(scores)`."}],"forbid":[]}]}