{"id":"recap-methods-lists-arrays","slug":"methods-lists-arrays","title":"Methods, lists and arrays","text":"A method with a clear job, a name and a return value keeps `main` short. Methods that take a list or an array and give back an answer come up in almost every program.\n\n### The tools\n\n| Tool | What it does | Taught in |\n| --- | --- | --- |\n| `public static int total(int[] values)` | a method with parameters and a return value | module 10, Methods and parameters, and module 11, Return values and the call stack |\n| `ArrayList<Integer>`, `add`, `get`, `size` | a list that grows as values are added | module 13, Lists |\n| for-each, `contains`, `indexOf`, `remove` | go through a list, and search it | module 14, For-each, list methods and lists in methods |\n| a list as a parameter | the method gets the caller's list itself, not a copy | module 14 |\n| `int[] bags = {14, 9, 22};`, `bags.length` | an array: a fixed number of values | module 15, Arrays |\n| `Collections.sort(list)`, `Arrays.sort(array)` | sort in place | module 28, Sorting and searching |\n| the index of the smallest or largest value, linear search | where a value is | module 15, Arrays, and module 28, Sorting and searching |\n\n### A method that returns a new list\n\nA potato farmer at the farmers' market sells potatoes in 2-kilo bags, and weighs every bag, in grams. A bag under 2000 grams can't be sold as 2 kilos. The method `lighterThan` gives back the bags that are too light:\n\n```java\nimport java.util.ArrayList;\nimport java.util.Collections;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> bags = new ArrayList<>();\n        bags.add(2050);\n        bags.add(1890);\n        bags.add(2010);\n        bags.add(1975);\n        bags.add(2100);\n        ArrayList<Integer> light = lighterThan(bags, 2000);\n        System.out.println(\"Too light: \" + light);\n        System.out.println(\"All bags: \" + bags);\n        Collections.sort(bags);\n        System.out.println(\"Lightest to heaviest: \" + bags);\n    }\n\n    public static ArrayList<Integer> lighterThan(ArrayList<Integer> bags, int limit) {\n        ArrayList<Integer> light = new ArrayList<>();\n        for (int bag : bags) {\n            if (bag < limit) {\n                light.add(bag);\n            }\n        }\n        return light;\n    }\n}\n```\n\n```output\nToo light: [1890, 1975]\nAll bags: [2050, 1890, 2010, 1975, 2100]\nLightest to heaviest: [1890, 1975, 2010, 2050, 2100]\n```\n\n- The return type `ArrayList<Integer>` says what the method gives back. It makes a new list, fills it, and returns it, so `main` gets the light bags, and the list of all bags stays as it was.\n- `Collections.sort(bags)` returns nothing. It sorts the list it gets, in place: the old order is gone.\n- A method that gets a list gets the caller's own list, not a copy (module 14). So a method that sorts or removes from its parameter changes the caller's list too. When the caller still needs the list as it was, the method should build a new one instead.\n\n### A method that returns an index\n\nThe same stall keeps the bags it sold on each market day in an array, and the day names in a second array, in the same order. `indexOfLargest` finds the largest value the way module 28 found the smallest, and it returns the index, which fits both arrays:\n\n```java\npublic class Main {\n    public static void main(String[] args) {\n        String[] days = {\"Wed\", \"Thu\", \"Fri\", \"Sat\"};\n        int[] sold = {14, 9, 22, 31};\n        int best = indexOfLargest(sold);\n        System.out.println(\"Best day: \" + days[best] + \", \" + sold[best] + \" bags\");\n        System.out.println(\"Bags in all: \" + total(sold));\n    }\n\n    public static int indexOfLargest(int[] values) {\n        int largest = 0;\n        for (int i = 1; i < values.length; i++) {\n            if (values[i] > values[largest]) {\n                largest = i;\n            }\n        }\n        return largest;\n    }\n\n    public static int total(int[] values) {\n        int sum = 0;\n        for (int value : values) {\n            sum += value;\n        }\n        return sum;\n    }\n}\n```\n\n```output\nBest day: Sat, 31 bags\nBags in all: 76\n```\n\n- With the index, `main` can look up both the day and the number. With only the number 31, it couldn't tell which day it was.\n- A for-each loop works on an array too, when the loop needs the values and not their indexes.\n","task":"A cheese stall cuts pieces from big wheels of cheese, and weighs each piece in grams. The pieces from 200 to 300 grams go in the basket labeled \"about 250 g\". Write the method `between(ArrayList<Integer> weights, int low, int high)`. It returns a new list of the weights from `low` to `high`, both included, in the order they're in. The list it gets must stay as it was. The check runs:\n\n```java\nArrayList<Integer> pieces = new ArrayList<>();\npieces.add(240);\npieces.add(310);\npieces.add(195);\npieces.add(300);\npieces.add(200);\nSystem.out.println(between(pieces, 200, 300));\nSystem.out.println(pieces);\n```\n\nand expects:\n\n```\n[240, 300, 200]\n[240, 310, 195, 300, 200]\n```\n","kind":"code","seed":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> pieces = new ArrayList<>();\n        pieces.add(240);\n        pieces.add(310);\n        pieces.add(195);\n        pieces.add(300);\n        pieces.add(200);\n        System.out.println(between(pieces, 200, 300));\n        System.out.println(pieces);\n    }\n\n    // Write the method between here.\n}\n","solution":"import java.util.ArrayList;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> pieces = new ArrayList<>();\n        pieces.add(240);\n        pieces.add(310);\n        pieces.add(195);\n        pieces.add(300);\n        pieces.add(200);\n        System.out.println(between(pieces, 200, 300));\n        System.out.println(pieces);\n    }\n\n    public static ArrayList<Integer> between(ArrayList<Integer> weights, int low, int high) {\n        ArrayList<Integer> result = new ArrayList<>();\n        for (int weight : weights) {\n            if (weight >= low && weight <= high) {\n                result.add(weight);\n            }\n        }\n        return result;\n    }\n}\n","hints":["The method starts `public static ArrayList<Integer> between(ArrayList<Integer> weights, int low, int high) {`. Make a new, empty list first, and return it at the end.","Go through `weights` with a for-each loop, and add a weight to the new list when `weight >= low && weight <= high`. Don't remove anything from `weights`: it's the caller's own list."],"tests":[{"name":"Test 1","stdin":"","call":"ArrayList<Integer> pieces = new ArrayList<>();\npieces.add(240);\npieces.add(310);\npieces.add(195);\npieces.add(300);\npieces.add(200);\nSystem.out.println(between(pieces, 200, 300));\nSystem.out.println(pieces);\n","expect":"[240, 300, 200]\n[240, 310, 195, 300, 200]","hidden":false},{"name":"Test 2","stdin":"","call":"ArrayList<Integer> pieces = new ArrayList<>();\npieces.add(150);\npieces.add(450);\nSystem.out.println(between(pieces, 200, 300));\nSystem.out.println(between(new ArrayList<>(), 1, 5));\nSystem.out.println(between(pieces, 100, 500) + \" \" + pieces.size());\n","expect":"[]\n[]\n[150, 450] 2","hidden":true},{"name":"Test 3","stdin":"","call":"ArrayList<Integer> pieces = new ArrayList<>();\npieces.add(80);\npieces.add(99);\npieces.add(100);\npieces.add(101);\nArrayList<Integer> result = between(pieces, 99, 100);\nresult.add(7);\nSystem.out.println(result);\nSystem.out.println(pieces);\n","expect":"[99, 100, 7]\n[80, 99, 100, 101]","hidden":true}],"require":[{"pattern":"\\bpublic\\s+static\\s+ArrayList<Integer>\\s+between\\s*\\(\\s*ArrayList<Integer>\\s+\\w+\\s*,\\s*int\\s+\\w+\\s*,\\s*int\\s+\\w+\\s*\\)","message":"Write the method as `public static ArrayList<Integer> between(ArrayList<Integer> weights, int low, int high)`."}],"forbid":[],"more":[{"task":"A stall's prices are in cents, and `cheapest` gives back the cheapest ones. What does this program print? Watch what happens to the list that `main` hands the method.\n","kind":"predict","seed":"import java.util.ArrayList;\nimport java.util.Collections;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> prices = new ArrayList<>();\n        prices.add(450);\n        prices.add(200);\n        prices.add(325);\n        ArrayList<Integer> cheap = cheapest(prices, 2);\n        System.out.println(cheap);\n        System.out.println(prices);\n        System.out.println(cheap.size() + prices.size());\n    }\n\n    public static ArrayList<Integer> cheapest(ArrayList<Integer> prices, int count) {\n        Collections.sort(prices);\n        ArrayList<Integer> result = new ArrayList<>();\n        for (int i = 0; i < count; i++) {\n            result.add(prices.get(i));\n        }\n        return result;\n    }\n}\n","solution":"import java.util.ArrayList;\nimport java.util.Collections;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> prices = new ArrayList<>();\n        prices.add(450);\n        prices.add(200);\n        prices.add(325);\n        ArrayList<Integer> cheap = cheapest(prices, 2);\n        System.out.println(cheap);\n        System.out.println(prices);\n        System.out.println(cheap.size() + prices.size());\n    }\n\n    public static ArrayList<Integer> cheapest(ArrayList<Integer> prices, int count) {\n        Collections.sort(prices);\n        ArrayList<Integer> result = new ArrayList<>();\n        for (int i = 0; i < count; i++) {\n            result.add(prices.get(i));\n        }\n        return result;\n    }\n}\n","hints":["`cheapest` sorts its parameter, and then copies the first `count` prices into a new list. The new list holds the two cheapest prices.","The parameter `prices` is the same list as `main`'s `prices`, not a copy, so `main` sees it sorted too. The last line adds up the sizes of the two lists."],"tests":[{"name":"Output","stdin":"","expect":"[200, 325]\n[200, 325, 450]\n5","hidden":false}],"require":[],"forbid":[],"lines":["[200, 325]","[200, 325, 450]","5"]},{"task":"A bakery stall lists its bread prices, in cents, in an array, in the order the loaves lie on the table. For the sign, it wants the prices sorted from the cheapest up, but the table order must stay as it is. Write the method `sortedCopy(int[] prices)`. It returns a new array with the same prices, sorted, and leaves the array it gets as it was. Make the new array with `new int[prices.length]`, copy the prices into it, and sort the copy with `Arrays.sort`. The check runs:\n\n```java\nint[] prices = {850, 600, 1200, 600};\nint[] sorted = sortedCopy(prices);\nSystem.out.println(Arrays.toString(sorted));\nSystem.out.println(Arrays.toString(prices));\n```\n\nand expects:\n\n```\n[600, 600, 850, 1200]\n[850, 600, 1200, 600]\n```\n","kind":"code","seed":"import java.util.Arrays;\n\npublic class Main {\n    public static void main(String[] args) {\n        int[] prices = {850, 600, 1200, 600};\n        int[] sorted = sortedCopy(prices);\n        System.out.println(Arrays.toString(sorted));\n        System.out.println(Arrays.toString(prices));\n    }\n\n    // Write the method sortedCopy here.\n}\n","solution":"import java.util.Arrays;\n\npublic class Main {\n    public static void main(String[] args) {\n        int[] prices = {850, 600, 1200, 600};\n        int[] sorted = sortedCopy(prices);\n        System.out.println(Arrays.toString(sorted));\n        System.out.println(Arrays.toString(prices));\n    }\n\n    public static int[] sortedCopy(int[] prices) {\n        int[] copy = new int[prices.length];\n        for (int i = 0; i < prices.length; i++) {\n            copy[i] = prices[i];\n        }\n        Arrays.sort(copy);\n        return copy;\n    }\n}\n","hints":["The method starts `public static int[] sortedCopy(int[] prices) {`. `int[] copy = new int[prices.length];` makes an array of the same size, full of zeros.","Copy each price with `for (int i = 0; i < prices.length; i++) { copy[i] = prices[i]; }`, then `Arrays.sort(copy);` and `return copy;`. Sorting `prices` itself would change the caller's array."],"tests":[{"name":"Test 1","stdin":"","call":"int[] prices = {850, 600, 1200, 600};\nint[] sorted = sortedCopy(prices);\nSystem.out.println(Arrays.toString(sorted));\nSystem.out.println(Arrays.toString(prices));\n","expect":"[600, 600, 850, 1200]\n[850, 600, 1200, 600]","hidden":false},{"name":"Test 2","stdin":"","call":"int[] prices = {5, 4, 3, 2, 1};\nint[] sorted = sortedCopy(prices);\nSystem.out.println(Arrays.toString(sorted) + \" \" + Arrays.toString(prices));\nSystem.out.println(sorted == prices);\n","expect":"[1, 2, 3, 4, 5] [5, 4, 3, 2, 1]\nfalse","hidden":true},{"name":"Test 3","stdin":"","call":"int[] none = new int[0];\nSystem.out.println(Arrays.toString(sortedCopy(none)));\nint[] one = {990};\nint[] copy = sortedCopy(one);\ncopy[0] = 1;\nSystem.out.println(one[0] + \" \" + copy[0]);\n","expect":"[]\n990 1","hidden":true}],"require":[{"pattern":"\\bpublic\\s+static\\s+int\\s*\\[\\s*\\]\\s*sortedCopy\\s*\\(\\s*int\\s*\\[\\s*\\]\\s*\\w+\\s*\\)","message":"Write the method as `public static int[] sortedCopy(int[] prices)`."},{"pattern":"\\bArrays\\s*\\.\\s*sort\\s*\\(","message":"Sort the copy with `Arrays.sort`."}],"forbid":[]}]}