{"id":"sorting-objects-comparator","slug":"comparator","title":"Comparator: an order given to the sort","text":"A class has only one `compareTo`, so it has only one natural order. But a program often needs the same objects in several orders. An airport's departures board lists the flights by time, the staff at the gates want them by gate, and a travel app lists them by destination. For those, you hand the sort the order to use, as a lambda.\n\n### A lambda that compares two objects\n\nA list has a `sort` method of its own, which takes the rule as a lambda with two parameters (module 37 showed that two parameters go in parentheses: `(a, b) -> ...`). The board's flights, by gate:\n\n```java\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Flight> flights = new ArrayList<>();\n        flights.add(new Flight(\"Lisbon\", \"13:10\", 4));\n        flights.add(new Flight(\"Oslo\", \"07:45\", 12));\n        flights.add(new Flight(\"Dublin\", \"09:30\", 7));\n        flights.add(new Flight(\"Athens\", \"18:20\", 2));\n        flights.add(new Flight(\"Riga\", \"09:05\", 12));\n\n        flights.sort((a, b) -> Integer.compare(a.getGate(), b.getGate()));\n        for (Flight flight : flights) {\n            System.out.println(flight);\n        }\n    }\n}\n// ==== Flight.java ====\npublic class Flight {\n    private String destination;\n    private String departs;\n    private int gate;\n\n    public Flight(String destination, String departs, int gate) {\n        this.destination = destination;\n        this.departs = departs;\n        this.gate = gate;\n    }\n\n    public String getDestination() {\n        return this.destination;\n    }\n\n    public String getDeparts() {\n        return this.departs;\n    }\n\n    public int getGate() {\n        return this.gate;\n    }\n\n    @Override\n    public String toString() {\n        return this.departs + \" \" + this.destination + \" (gate \" + this.gate + \")\";\n    }\n}\n```\n\n```output\n18:20 Athens (gate 2)\n13:10 Lisbon (gate 4)\n09:30 Dublin (gate 7)\n07:45 Oslo (gate 12)\n09:05 Riga (gate 12)\n```\n\n- Flight has no `compareTo`, and it doesn't implement Comparable. The whole rule is in the lambda.\n- The lambda gets two flights, `a` and `b`, and answers the way `compareTo` does: negative when `a` goes before `b`, zero for a tie, positive when `a` goes after `b`. `Integer.compare(a.getGate(), b.getGate())` puts the smaller gate first.\n- `a` and `b` are names like any others: `(first, second) -> ...` works the same.\n- `sort` changes the list itself, as `Collections.sort` does. Ties keep their order here too: Oslo and Riga both leave from gate 12, and Oslo was in the list first.\n\n### The Comparator interface\n\nThe lambda is a **Comparator**, another of Java's interfaces. The one method you have to write for a comparator, the one the lambda writes, is `compare(a, b)`, which answers like `compareTo`, but for two objects given to it from outside. Every comparator also comes with ready-made methods, such as `reversed()` and `thenComparing()` later in this module. A comparator can be kept in a variable of type `Comparator<Flight>` and used as often as you like, and `Collections.sort` takes one as its second parameter:\n\n```java\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Flight> flights = new ArrayList<>();\n        flights.add(new Flight(\"Lisbon\", \"13:10\", 4));\n        flights.add(new Flight(\"Oslo\", \"07:45\", 12));\n        flights.add(new Flight(\"Dublin\", \"09:30\", 7));\n        flights.add(new Flight(\"Athens\", \"18:20\", 2));\n        flights.add(new Flight(\"Riga\", \"09:05\", 12));\n\n        Comparator<Flight> byTime = (a, b) -> a.getDeparts().compareTo(b.getDeparts());\n        Collections.sort(flights, byTime);\n        for (Flight flight : flights) {\n            System.out.println(flight);\n        }\n    }\n}\n// ==== Flight.java ====\npublic class Flight {\n    private String destination;\n    private String departs;\n    private int gate;\n\n    public Flight(String destination, String departs, int gate) {\n        this.destination = destination;\n        this.departs = departs;\n        this.gate = gate;\n    }\n\n    public String getDestination() {\n        return this.destination;\n    }\n\n    public String getDeparts() {\n        return this.departs;\n    }\n\n    public int getGate() {\n        return this.gate;\n    }\n\n    @Override\n    public String toString() {\n        return this.departs + \" \" + this.destination + \" (gate \" + this.gate + \")\";\n    }\n}\n```\n\n```output\n07:45 Oslo (gate 12)\n09:05 Riga (gate 12)\n09:30 Dublin (gate 7)\n13:10 Lisbon (gate 4)\n18:20 Athens (gate 2)\n```\n\n- `Comparator` is in `java.util`, so the program imports it: `import java.util.Comparator;`.\n- The type `Comparator<Flight>` tells Java that the lambda's `a` and `b` are Flights.\n- `Collections.sort(flights, byTime)` and `flights.sort(byTime)` do the same thing. This module mostly writes the shorter `flights.sort(...)`.\n- The times are Strings, and Strings sort letter by letter. Every time here has two digits for the hour, like `07:45`, so alphabetical order is time order. Written as `7:45`, it would come after `13:10`, since the character 7 comes after 1.\n\n### Comparator.comparing\n\nMost comparators compare one value of each object, such as the gate or the time. `Comparator.comparing` builds that comparator for you, from a method that gives the value, usually a getter written as a method reference (module 37):\n\n```java\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Flight> flights = new ArrayList<>();\n        flights.add(new Flight(\"Lisbon\", \"13:10\", 4));\n        flights.add(new Flight(\"Oslo\", \"07:45\", 12));\n        flights.add(new Flight(\"Dublin\", \"09:30\", 7));\n        flights.add(new Flight(\"Athens\", \"18:20\", 2));\n        flights.add(new Flight(\"Riga\", \"09:05\", 12));\n\n        flights.sort(Comparator.comparing(Flight::getDestination));\n        for (Flight flight : flights) {\n            System.out.println(flight);\n        }\n    }\n}\n// ==== Flight.java ====\npublic class Flight {\n    private String destination;\n    private String departs;\n    private int gate;\n\n    public Flight(String destination, String departs, int gate) {\n        this.destination = destination;\n        this.departs = departs;\n        this.gate = gate;\n    }\n\n    public String getDestination() {\n        return this.destination;\n    }\n\n    public String getDeparts() {\n        return this.departs;\n    }\n\n    public int getGate() {\n        return this.gate;\n    }\n\n    @Override\n    public String toString() {\n        return this.departs + \" \" + this.destination + \" (gate \" + this.gate + \")\";\n    }\n}\n```\n\n```output\n18:20 Athens (gate 2)\n09:30 Dublin (gate 7)\n13:10 Lisbon (gate 4)\n07:45 Oslo (gate 12)\n09:05 Riga (gate 12)\n```\n\n`Comparator.comparing(Flight::getDestination)` reads: to compare two flights, call `getDestination()` on each, and compare those values. So the values need an order of their own: numbers, Strings, or objects of a Comparable class like step 1's Talk. The two comparators above, built this way:\n\n- `Comparator.comparing(Flight::getGate)` does what `(a, b) -> Integer.compare(a.getGate(), b.getGate())` did.\n- `Comparator.comparing(Flight::getDeparts)` does what `byTime` did.\n\n### reversed\n\n`reversed()` turns a comparator around: the largest first, or Z to A. The board's evening view shows the latest flights first:\n\n```java\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Flight> flights = new ArrayList<>();\n        flights.add(new Flight(\"Lisbon\", \"13:10\", 4));\n        flights.add(new Flight(\"Oslo\", \"07:45\", 12));\n        flights.add(new Flight(\"Dublin\", \"09:30\", 7));\n        flights.add(new Flight(\"Athens\", \"18:20\", 2));\n        flights.add(new Flight(\"Riga\", \"09:05\", 12));\n\n        flights.sort(Comparator.comparing(Flight::getDeparts).reversed());\n        for (Flight flight : flights) {\n            System.out.println(flight);\n        }\n        System.out.println();\n\n        flights.sort(Comparator.comparing(Flight::getGate).reversed());\n        for (Flight flight : flights) {\n            System.out.println(flight);\n        }\n    }\n}\n// ==== Flight.java ====\npublic class Flight {\n    private String destination;\n    private String departs;\n    private int gate;\n\n    public Flight(String destination, String departs, int gate) {\n        this.destination = destination;\n        this.departs = departs;\n        this.gate = gate;\n    }\n\n    public String getDestination() {\n        return this.destination;\n    }\n\n    public String getDeparts() {\n        return this.departs;\n    }\n\n    public int getGate() {\n        return this.gate;\n    }\n\n    @Override\n    public String toString() {\n        return this.departs + \" \" + this.destination + \" (gate \" + this.gate + \")\";\n    }\n}\n```\n\n```output\n18:20 Athens (gate 2)\n13:10 Lisbon (gate 4)\n09:30 Dublin (gate 7)\n09:05 Riga (gate 12)\n07:45 Oslo (gate 12)\n\n09:05 Riga (gate 12)\n07:45 Oslo (gate 12)\n09:30 Dublin (gate 7)\n13:10 Lisbon (gate 4)\n18:20 Athens (gate 2)\n```\n\nLook at Riga and Oslo in the second list. `reversed()` turns the comparator's answers around, not the list: flights that tie still tie, and a tie keeps the order the list had. After the first sort, Riga was before Oslo, so it stays before Oslo.\n\nA lambda you write yourself turns around by swapping the two values, `(a, b) -> Integer.compare(b.getGate(), a.getGate())`, just as swapping them in step 1's `compareTo` put the latest talk first.\n\n### Use a method reference in comparing\n\n`Comparator.comparing(flight -> flight.getGate())` works too, on its own. But with `.reversed()` after it, it doesn't compile:\n\n```java\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Flight> flights = new ArrayList<>();\n        flights.add(new Flight(\"Lisbon\", \"13:10\", 4));\n        flights.add(new Flight(\"Oslo\", \"07:45\", 12));\n        flights.sort(Comparator.comparing(flight -> flight.getGate()).reversed());\n        System.out.println(flights);\n    }\n}\n// ==== Flight.java ====\npublic class Flight {\n    private String destination;\n    private String departs;\n    private int gate;\n\n    public Flight(String destination, String departs, int gate) {\n        this.destination = destination;\n        this.departs = departs;\n        this.gate = gate;\n    }\n\n    public int getGate() {\n        return this.gate;\n    }\n\n    @Override\n    public String toString() {\n        return this.departs + \" \" + this.destination + \" (gate \" + this.gate + \")\";\n    }\n}\n```\n\n```javac\nMain.java:10: error: cannot find symbol\n        flights.sort(Comparator.comparing(flight -> flight.getGate()).reversed());\n                                                          ^\n  symbol:   method getGate()\n  location: variable flight of type Object\n1 error\n```\n\nJava works out a lambda's parameter types from the place where the lambda is used. Here, `.reversed()` is called on the comparator before Java has seen that it's meant for flights, so it takes `flight` to be just an Object, which has no `getGate()`. The method reference `Flight::getGate` names the class, so Java knows. Write method references in `comparing`, as the rest of this module does.\n","task":"A podcast app plays the short episodes first. `Episode.java` is ready: an episode has a title and a length in minutes, and no `compareTo`. In `Main.java`, write the method `sortShortestFirst(List<Episode> episodes)`, which sorts the list, the shortest episode first. Episodes of the same length keep the order they had in the list. Use the list's own `sort` with a lambda of two episodes: `episodes.sort((a, b) -> ...)`. The check runs:\n\n```java\nList<Episode> queue = new ArrayList<>();\nqueue.add(new Episode(\"The deep sea\", 48));\nqueue.add(new Episode(\"Tiny houses\", 22));\nqueue.add(new Episode(\"Night trains\", 35));\nsortShortestFirst(queue);\nSystem.out.println(queue);\n```\n\nand expects:\n\n```\n[Tiny houses (22 min), Night trains (35 min), The deep sea (48 min)]\n```\n","kind":"code","seed":"// ==== Main.java ====\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Episode> queue = new ArrayList<>();\n        queue.add(new Episode(\"The deep sea\", 48));\n        queue.add(new Episode(\"Tiny houses\", 22));\n        queue.add(new Episode(\"Night trains\", 35));\n        sortShortestFirst(queue);\n        System.out.println(queue);\n    }\n\n    // Write the method sortShortestFirst here.\n}\n\n// ==== Episode.java ====\npublic class Episode {\n    private String title;\n    private int minutes;\n\n    public Episode(String title, int minutes) {\n        this.title = title;\n        this.minutes = minutes;\n    }\n\n    public String getTitle() {\n        return this.title;\n    }\n\n    public int getMinutes() {\n        return this.minutes;\n    }\n\n    @Override\n    public String toString() {\n        return this.title + \" (\" + this.minutes + \" min)\";\n    }\n}\n","solution":"// ==== Main.java ====\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Episode> queue = new ArrayList<>();\n        queue.add(new Episode(\"The deep sea\", 48));\n        queue.add(new Episode(\"Tiny houses\", 22));\n        queue.add(new Episode(\"Night trains\", 35));\n        sortShortestFirst(queue);\n        System.out.println(queue);\n    }\n\n    public static void sortShortestFirst(List<Episode> episodes) {\n        episodes.sort((a, b) -> Integer.compare(a.getMinutes(), b.getMinutes()));\n    }\n}\n\n// ==== Episode.java ====\npublic class Episode {\n    private String title;\n    private int minutes;\n\n    public Episode(String title, int minutes) {\n        this.title = title;\n        this.minutes = minutes;\n    }\n\n    public String getTitle() {\n        return this.title;\n    }\n\n    public int getMinutes() {\n        return this.minutes;\n    }\n\n    @Override\n    public String toString() {\n        return this.title + \" (\" + this.minutes + \" min)\";\n    }\n}\n","hints":["The header is `public static void sortShortestFirst(List<Episode> episodes)`. It returns nothing: `sort` changes the list it's called on.","The lambda gets two episodes and compares their lengths: `episodes.sort((a, b) -> Integer.compare(a.getMinutes(), b.getMinutes()));`."],"tests":[{"name":"Test 1","stdin":"","call":"List<Episode> queue = new ArrayList<>();\nqueue.add(new Episode(\"The deep sea\", 48));\nqueue.add(new Episode(\"Tiny houses\", 22));\nqueue.add(new Episode(\"Night trains\", 35));\nsortShortestFirst(queue);\nSystem.out.println(queue);\n","expect":"[Tiny houses (22 min), Night trains (35 min), The deep sea (48 min)]","hidden":false},{"name":"Test 2","stdin":"","call":"List<Episode> queue = new ArrayList<>();\nsortShortestFirst(queue);\nSystem.out.println(queue);\nqueue.add(new Episode(\"Bees\", 61));\nqueue.add(new Episode(\"Lighthouses\", 19));\nqueue.add(new Episode(\"Maps\", 61));\nqueue.add(new Episode(\"Salt\", 5));\nqueue.add(new Episode(\"Clocks\", 19));\nsortShortestFirst(queue);\nSystem.out.println(queue);\n","expect":"[]\n[Salt (5 min), Lighthouses (19 min), Clocks (19 min), Bees (61 min), Maps (61 min)]","hidden":true}],"require":[{"pattern":"\\.sort\\s*\\(\\s*\\([^()]*\\)\\s*->","message":"Sort with the list's own `sort` and a lambda of two episodes, like `episodes.sort((a, b) -> ...)`."}],"forbid":[{"pattern":"\\bimplements\\s+Comparable\\b","message":"Episode stays as it is. The order goes in the lambda that you give to `sort`."}],"more":[{"task":"A ski resort's app shows its slopes in different orders. Each slope has a name and the centimeters of fresh snow on it. What does this program print?\n","kind":"predict","seed":"import java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Slope> slopes = new ArrayList<>();\n        slopes.add(new Slope(\"Summit\", 8));\n        slopes.add(new Slope(\"Glacier\", 25));\n        slopes.add(new Slope(\"Pine\", 0));\n        slopes.add(new Slope(\"Eagle\", 25));\n\n        slopes.sort(Comparator.comparing(Slope::getSnow).reversed());\n        System.out.println(slopes.get(0) + \" \" + slopes.get(1));\n\n        Comparator<Slope> byName = Comparator.comparing(Slope::getName);\n        Collections.sort(slopes, byName);\n        System.out.println(slopes.get(0) + \" \" + slopes.get(3));\n\n        slopes.sort(byName.reversed());\n        System.out.println(slopes.get(0));\n    }\n}\n// ==== Slope.java ====\npublic class Slope {\n    private String name;\n    private int snow;\n\n    public Slope(String name, int snow) {\n        this.name = name;\n        this.snow = snow;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getSnow() {\n        return this.snow;\n    }\n\n    @Override\n    public String toString() {\n        return this.name + \"(\" + this.snow + \")\";\n    }\n}\n","solution":"import java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Slope> slopes = new ArrayList<>();\n        slopes.add(new Slope(\"Summit\", 8));\n        slopes.add(new Slope(\"Glacier\", 25));\n        slopes.add(new Slope(\"Pine\", 0));\n        slopes.add(new Slope(\"Eagle\", 25));\n\n        slopes.sort(Comparator.comparing(Slope::getSnow).reversed());\n        System.out.println(slopes.get(0) + \" \" + slopes.get(1));\n\n        Comparator<Slope> byName = Comparator.comparing(Slope::getName);\n        Collections.sort(slopes, byName);\n        System.out.println(slopes.get(0) + \" \" + slopes.get(3));\n\n        slopes.sort(byName.reversed());\n        System.out.println(slopes.get(0));\n    }\n}\n// ==== Slope.java ====\npublic class Slope {\n    private String name;\n    private int snow;\n\n    public Slope(String name, int snow) {\n        this.name = name;\n        this.snow = snow;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getSnow() {\n        return this.snow;\n    }\n\n    @Override\n    public String toString() {\n        return this.name + \"(\" + this.snow + \")\";\n    }\n}\n","hints":["The first sort puts the most snow first. Glacier and Eagle both have 25: `reversed()` turns the comparator's answers around, but a tie is still a tie, so they keep the list's order, Glacier first.","`byName` sorts from A to Z: Eagle, Glacier, Pine, Summit. `byName.reversed()` sorts from Z to A."],"tests":[{"name":"Output","stdin":"","expect":"Glacier(25) Eagle(25)\nEagle(25) Summit(8)\nSummit(8)","hidden":false}],"require":[],"forbid":[],"lines":["Glacier(25) Eagle(25)","Eagle(25) Summit(8)","Summit(8)"]},{"task":"A phone's video app helps free up space by showing the largest videos first. `Video.java` is ready. In `Main.java`, write the method `largestFirst(List<Video> videos)`, which returns a **new** list of the videos, the largest first, and leaves the given list as it was. Copy the list with `new ArrayList<>(videos)`, and sort the copy with `Comparator.comparing` and `reversed()`. The check runs:\n\n```java\nList<Video> videos = new ArrayList<>();\nvideos.add(new Video(\"concert.mp4\", 240));\nvideos.add(new Video(\"cat.mp4\", 85));\nvideos.add(new Video(\"fireworks.mp4\", 310));\nSystem.out.println(largestFirst(videos));\nSystem.out.println(videos.get(0));\n```\n\nand expects:\n\n```\n[fireworks.mp4 310 MB, concert.mp4 240 MB, cat.mp4 85 MB]\nconcert.mp4 240 MB\n```\n","kind":"code","seed":"// ==== Main.java ====\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Video> videos = new ArrayList<>();\n        videos.add(new Video(\"concert.mp4\", 240));\n        videos.add(new Video(\"cat.mp4\", 85));\n        videos.add(new Video(\"fireworks.mp4\", 310));\n        System.out.println(largestFirst(videos));\n        System.out.println(videos.get(0));\n    }\n\n    // Write the method largestFirst here.\n}\n\n// ==== Video.java ====\npublic class Video {\n    private String file;\n    private int megabytes;\n\n    public Video(String file, int megabytes) {\n        this.file = file;\n        this.megabytes = megabytes;\n    }\n\n    public String getFile() {\n        return this.file;\n    }\n\n    public int getMegabytes() {\n        return this.megabytes;\n    }\n\n    @Override\n    public String toString() {\n        return this.file + \" \" + this.megabytes + \" MB\";\n    }\n}\n","solution":"// ==== Main.java ====\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<Video> videos = new ArrayList<>();\n        videos.add(new Video(\"concert.mp4\", 240));\n        videos.add(new Video(\"cat.mp4\", 85));\n        videos.add(new Video(\"fireworks.mp4\", 310));\n        System.out.println(largestFirst(videos));\n        System.out.println(videos.get(0));\n    }\n\n    public static List<Video> largestFirst(List<Video> videos) {\n        List<Video> sorted = new ArrayList<>(videos);\n        sorted.sort(Comparator.comparing(Video::getMegabytes).reversed());\n        return sorted;\n    }\n}\n\n// ==== Video.java ====\npublic class Video {\n    private String file;\n    private int megabytes;\n\n    public Video(String file, int megabytes) {\n        this.file = file;\n        this.megabytes = megabytes;\n    }\n\n    public String getFile() {\n        return this.file;\n    }\n\n    public int getMegabytes() {\n        return this.megabytes;\n    }\n\n    @Override\n    public String toString() {\n        return this.file + \" \" + this.megabytes + \" MB\";\n    }\n}\n","hints":["The header is `public static List<Video> largestFirst(List<Video> videos)`. Start with a copy, `List<Video> sorted = new ArrayList<>(videos);`, sort the copy, and return it.","`Comparator.comparing(Video::getMegabytes)` puts the smallest first, and `.reversed()` after it puts the largest first: `sorted.sort(Comparator.comparing(Video::getMegabytes).reversed());`."],"tests":[{"name":"Test 1","stdin":"","call":"List<Video> videos = new ArrayList<>();\nvideos.add(new Video(\"concert.mp4\", 240));\nvideos.add(new Video(\"cat.mp4\", 85));\nvideos.add(new Video(\"fireworks.mp4\", 310));\nSystem.out.println(largestFirst(videos));\nSystem.out.println(videos.get(0));\n","expect":"[fireworks.mp4 310 MB, concert.mp4 240 MB, cat.mp4 85 MB]\nconcert.mp4 240 MB","hidden":false},{"name":"Test 2","stdin":"","call":"List<Video> videos = new ArrayList<>();\nSystem.out.println(largestFirst(videos));\nvideos.add(new Video(\"a.mp4\", 12));\nvideos.add(new Video(\"b.mp4\", 400));\nvideos.add(new Video(\"c.mp4\", 12));\nvideos.add(new Video(\"d.mp4\", 1));\nvideos.add(new Video(\"e.mp4\", 400));\nList<Video> sorted = largestFirst(videos);\nSystem.out.println(sorted);\nSystem.out.println(videos);\n","expect":"[]\n[b.mp4 400 MB, e.mp4 400 MB, a.mp4 12 MB, c.mp4 12 MB, d.mp4 1 MB]\n[a.mp4 12 MB, b.mp4 400 MB, c.mp4 12 MB, d.mp4 1 MB, e.mp4 400 MB]","hidden":true}],"require":[{"pattern":"\\bComparator\\s*\\.\\s*comparing\\s*\\(","message":"Build the comparator with `Comparator.comparing`, for example `Comparator.comparing(Video::getMegabytes)`."},{"pattern":"\\.reversed\\s*\\(\\s*\\)","message":"Turn the comparator around with `reversed()`, so the largest video comes first."}],"forbid":[]}]}