{"id":"linked-structures-array-deque","slug":"array-deque","title":"ArrayDeque from the library","text":"Java has a ready-made class for stacks and queues: `ArrayDeque`, in `java.util`. A **deque** (said \"deck\", short for double-ended queue) can add and remove at both of its ends, so it can be a stack or a queue. Unlike the classes this module has built so far, an ArrayDeque keeps its values in an array, not in nodes: an array that it replaces with a bigger one when it's full, like an ArrayList. Unlike an ArrayList, it doesn't shift the other values along when you add or remove at the front. Java's documentation says that most of its operations run in amortized constant time: the same few steps whatever the size, apart from the occasional copy into a bigger array.\n\n### As a stack\n\n`push`, `pop` and `peek` work at the front of the deque, which is the stack's top. A painter puts coats of paint on a wall; the last coat is the one you see:\n\n```java\nimport java.util.ArrayDeque;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayDeque<String> coats = new ArrayDeque<>();\n        coats.push(\"primer\");\n        coats.push(\"white\");\n        coats.push(\"sea blue\");\n        System.out.println(coats);\n        System.out.println(\"Scraped off: \" + coats.pop());\n        System.out.println(\"Now showing: \" + coats.peek());\n        System.out.println(coats + \", \" + coats.size() + \" coats\");\n    }\n}\n```\n\n```output\n[sea blue, white, primer]\nScraped off: sea blue\nNow showing: white\n[white, primer], 2 coats\n```\n\nPrinting a deque, or going through it with a for-each loop, goes from the front to the back. For a stack, that's top first.\n\nJava also has an old class called `Stack`. Its own documentation recommends using a Deque such as ArrayDeque in preference to it.\n\n### As a queue\n\n`offer` adds at the back, and `poll` removes from the front and returns what it removed. `peek` looks at the front. A juice bar makes the drinks in the order they were ordered:\n\n```java\nimport java.util.ArrayDeque;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayDeque<String> orders = new ArrayDeque<>();\n        orders.offer(\"orange\");\n        orders.offer(\"mango\");\n        orders.offer(\"beet and apple\");\n        System.out.println(\"Making \" + orders.poll());\n        System.out.println(\"Next up: \" + orders.peek());\n        System.out.println(\"Waiting: \" + orders);\n        orders.poll();\n        orders.poll();\n        System.out.println(orders.poll());\n        System.out.println(orders.isEmpty());\n    }\n}\n```\n\n```output\nMaking orange\nNext up: mango\nWaiting: [mango, beet and apple]\nnull\ntrue\n```\n\nOn an empty deque, `poll` and `peek` return `null`, while `pop` throws a NoSuchElementException. An ArrayDeque doesn't accept `null` as a value (adding one throws a NullPointerException), so a `null` from `poll` always means that the deque was empty.\n\n### Both ends\n\nEach end has its own methods too: `addFirst` and `addLast`, `offerFirst` and `offerLast`, `removeFirst` and `removeLast`, `peekFirst` and `peekLast`, `pollFirst` and `pollLast`. `push` is the same as `addFirst`, `pop` as `removeFirst`, `offer` as `offerLast` and `poll` as `pollFirst`. A deque used as a stack at its back end (`addLast` and `removeLast`) keeps its values in the order they were added, which is handy when you print them. `clear()` empties a deque.\n\nThe variable can have the interface's type, as with `List` and ArrayList: `Deque<String> coats = new ArrayDeque<>();` (with `import java.util.Deque;`). With `var` (module 57), `var coats = new ArrayDeque<String>();` works too.\n","task":"A web browser keeps the pages you've opened on a stack, so that its back button can return to the page before. The program reads lines until the line `end`:\n\n- `back` closes the page on top and prints `back to ` and the page that is now on top. When fewer than two pages are open, it prints `can't go back` instead and changes nothing.\n- Any other line is the name of a page to open: it goes on top.\n\nAt `end`, the program prints `now at ` and the page on top, or `no page open` if there is none. Use an ArrayDeque as the stack, with `push`, `pop` and `peek`. With this input:\n\n```input\nhome\nnews\nweather\nback\nsports\nback\nback\nback\nend\n```\n\nthe program prints:\n\n```\nback to news\nback to news\nback to home\ncan't go back\nnow at home\n```\n","kind":"code","seed":"import java.util.ArrayDeque;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        ArrayDeque<String> pages = new ArrayDeque<>();\n\n    }\n}\n","solution":"import java.util.ArrayDeque;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        ArrayDeque<String> pages = new ArrayDeque<>();\n        while (true) {\n            String line = scanner.nextLine();\n            if (line.equals(\"end\")) {\n                break;\n            }\n            if (line.equals(\"back\")) {\n                if (pages.size() < 2) {\n                    System.out.println(\"can't go back\");\n                } else {\n                    pages.pop();\n                    System.out.println(\"back to \" + pages.peek());\n                }\n            } else {\n                pages.push(line);\n            }\n        }\n        if (pages.isEmpty()) {\n            System.out.println(\"no page open\");\n        } else {\n            System.out.println(\"now at \" + pages.peek());\n        }\n    }\n}\n","hints":["Read lines in a `while (true)` loop that breaks at `end`. A page is opened with `pages.push(line);`.","For `back`, check `pages.size() < 2` first. Otherwise `pages.pop();` closes the top page, and `pages.peek()` is the page you're back to."],"tests":[{"name":"Test 1","stdin":"home\nnews\nweather\nback\nsports\nback\nback\nback\nend\n","expect":"back to news\nback to news\nback to home\ncan't go back\nnow at home","hidden":false},{"name":"Test 2","stdin":"end\n","expect":"no page open","hidden":true},{"name":"Test 3","stdin":"back\nrecipes\nback\nsoup\nbread\nback\nback\nend\n","expect":"can't go back\ncan't go back\nback to soup\nback to recipes\nnow at recipes","hidden":true},{"name":"Test 4","stdin":"maps\nmaps\nback\nend\n","expect":"back to maps\nnow at maps","hidden":true}],"require":[{"pattern":"\\.push\\s*\\(","message":"Open a page by pushing it onto the ArrayDeque with `push`."}],"forbid":[],"more":[{"task":"A ticket office serves people in the order they joined the line. The program reads lines until `end`:\n\n- `join ` and a name: the person joins the back of the line;\n- `serve`: the person at the front leaves the line, and the program prints `serving ` and their name, or `nobody in line` when the line is empty.\n\nAt `end`, it prints `still waiting: ` and the line, front first, as an ArrayDeque prints itself. Use an ArrayDeque as a queue, with `offer` and `poll`. With this input:\n\n```input\njoin Ada\njoin Bo\nserve\njoin Cy\njoin Dee\nserve\nend\n```\n\nthe program prints:\n\n```\nserving Ada\nserving Bo\nstill waiting: [Cy, Dee]\n```\n","kind":"code","seed":"import java.util.ArrayDeque;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n\n    }\n}\n","solution":"import java.util.ArrayDeque;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        ArrayDeque<String> line = new ArrayDeque<>();\n        while (true) {\n            String command = scanner.nextLine();\n            if (command.equals(\"end\")) {\n                break;\n            }\n            if (command.startsWith(\"join \")) {\n                line.offer(command.substring(5));\n            } else if (command.equals(\"serve\")) {\n                String name = line.poll();\n                if (name == null) {\n                    System.out.println(\"nobody in line\");\n                } else {\n                    System.out.println(\"serving \" + name);\n                }\n            }\n        }\n        System.out.println(\"still waiting: \" + line);\n    }\n}\n","hints":["`command.startsWith(\"join \")` spots a join, and `command.substring(5)` is the name after it. `line.offer(name);` puts the person at the back.","`line.poll()` returns the person at the front, or `null` when the line is empty. At the end, `\"still waiting: \" + line` prints the deque in square brackets."],"tests":[{"name":"Test 1","stdin":"join Ada\njoin Bo\nserve\njoin Cy\njoin Dee\nserve\nend\n","expect":"serving Ada\nserving Bo\nstill waiting: [Cy, Dee]","hidden":false},{"name":"Test 2","stdin":"serve\njoin Eve\nserve\nserve\nend\n","expect":"nobody in line\nserving Eve\nnobody in line\nstill waiting: []","hidden":true},{"name":"Test 3","stdin":"join Finn\njoin Gus\njoin Hal\nend\n","expect":"still waiting: [Finn, Gus, Hal]","hidden":true}],"require":[{"pattern":"new\\s+ArrayDeque\\s*<","message":"Keep the line in an ArrayDeque."},{"pattern":"\\.poll\\s*\\(","message":"Serve the front of the line with `poll`."}],"forbid":[]},{"task":"A small text editor has undo and redo. The program reads lines until `end`:\n\n- `undo` takes back the last word typed that is still in the text. It prints `nothing to undo` when the text is empty.\n- `redo` puts back the word that the last `undo` took away (after two undos, two redos put both words back, in their order). It prints `nothing to redo` when there's nothing to put back. Typing a new word forgets everything that could still be redone.\n- Any other line is a word typed: it goes at the end of the text.\n\nAt `end`, the program prints the text, its words separated by single spaces, or `(empty)` when it has no words. Use two ArrayDeques: one for the words of the text, and one as a stack of the words that undo took away. With this input:\n\n```input\ndear\nold\nfriend\nundo\nundo\nredo\npal\nredo\nend\n```\n\nthe program prints:\n\n```\nnothing to redo\ndear old pal\n```\n","kind":"code","seed":"import java.util.ArrayDeque;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        ArrayDeque<String> words = new ArrayDeque<>();\n        ArrayDeque<String> undone = new ArrayDeque<>();\n\n    }\n}\n","solution":"import java.util.ArrayDeque;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        ArrayDeque<String> words = new ArrayDeque<>();\n        ArrayDeque<String> undone = new ArrayDeque<>();\n        while (true) {\n            String line = scanner.nextLine();\n            if (line.equals(\"end\")) {\n                break;\n            }\n            if (line.equals(\"undo\")) {\n                if (words.isEmpty()) {\n                    System.out.println(\"nothing to undo\");\n                } else {\n                    undone.push(words.removeLast());\n                }\n            } else if (line.equals(\"redo\")) {\n                if (undone.isEmpty()) {\n                    System.out.println(\"nothing to redo\");\n                } else {\n                    words.addLast(undone.pop());\n                }\n            } else {\n                words.addLast(line);\n                undone.clear();\n            }\n        }\n        if (words.isEmpty()) {\n            System.out.println(\"(empty)\");\n        } else {\n            System.out.println(String.join(\" \", words));\n        }\n    }\n}\n","hints":["Keep the text in `words` with `addLast` and take the last word back with `removeLast`, so the words stay in the order they were typed. `undo` pushes the removed word onto `undone`.","`redo` pops from `undone` and adds that word at the end of `words`. A typed word is added with `words.addLast(line);` and then `undone.clear();`. At the end, `String.join(\" \", words)` joins the words with spaces (module 39)."],"tests":[{"name":"Test 1","stdin":"dear\nold\nfriend\nundo\nundo\nredo\npal\nredo\nend\n","expect":"nothing to redo\ndear old pal","hidden":false},{"name":"Test 2","stdin":"undo\nredo\nend\n","expect":"nothing to undo\nnothing to redo\n(empty)","hidden":true},{"name":"Test 3","stdin":"see\nyou\nsoon\nundo\nundo\nundo\nundo\nredo\nredo\nredo\nredo\nend\n","expect":"nothing to undo\nnothing to redo\nsee you soon","hidden":true},{"name":"Test 4","stdin":"hello\nundo\nworld\nend\n","expect":"world","hidden":true}],"require":[],"forbid":[]}]}