Sorting in Java: Arrays, Lists, Maps, Streams, Comparators

Sort arrays, lists, streams, maps and sets in Java with Arrays.sort(), list.sort(), sorted() and Comparator chains. Also covers descending int[] arrays, null values, Collator, stable sorting and comparator mistakes that give wrong orders.

Java Sorting

Sorting in Java puts the elements of an array, a List, a Stream or a Map in order. The order can be the natural order of the elements, such as A to Z for text, or an order that we define ourselves with a Comparator.

We sort data whenever a user expects an order, such as a playlist sorted by title or a leaderboard with the highest score first. For a custom order, such as descending or by several fields, we build a Comparator with Comparator.comparing().

The following example sorts arrays, lists, streams and objects, with the result of each line as a comment.

// 1. Arrays
int[] numbers = {5, 3, 9, 1};
Arrays.sort(numbers);                                   // [1, 3, 5, 9]
String[] fruits = {"banana", "apple", "cherry"};
Arrays.sort(fruits, Comparator.reverseOrder());         // [cherry, banana, apple]

// 2. Lists
List<String> names = new ArrayList<>(List.of("Lokesh", "Alex", "John"));
Collections.sort(names);                                // [Alex, John, Lokesh]
names.sort(Comparator.reverseOrder());                  // [Lokesh, John, Alex]

// 3. Streams (a new list; the source stays unchanged)
List<Integer> sorted = Stream.of(5, 3, 9).sorted().toList();       // [3, 5, 9]

// 4. Objects: by artist, then by year; by plays, highest first
songs.sort(Comparator.comparing(Song::artist).thenComparing(Song::year));
                                                        // [Blue, Echo, Sun, Rain]
songs.sort(Comparator.comparing(Song::plays).reversed());          // [Echo, Rain, Blue, Sun]

// 5. Lists that contain null
List<String> withNull = Arrays.asList("pear", null, "fig");
withNull.sort(Comparator.nullsFirst(Comparator.naturalOrder()));   // [null, fig, pear]

Notice that Arrays.sort() and list.sort() change the original array or list, whereas sorted() returns a new list and leaves the source alone.

Next, we see when to use Comparable and when to use Comparator, and then we move on to arrays (including descending int[] arrays, ranges and parallelSort()), lists, maps and sets. Then we sort String values without case problems and by the rules of a language. The last part covers stable sorting and the comparator mistakes that give a wrong order without any exception.

1. Which Sort Method to Use for Which Data

Java has no single sort() method for every type, because each data structure has its own method. Some methods sort in place, which means the original array or list changes, whereas other methods leave the original alone and return a new sorted copy.

Table diagram with three columns. A primitive array uses Arrays.sort or Arrays.parallelSort. The array is sorted in place, in ascending order, without a Comparator. An object array uses Arrays.sort with or without a Comparator, in place and stable. A List uses list.sort or Collections.sort, in place and stable. A Stream uses sorted().toList() and returns a new list. A Map uses new TreeMap or entrySet().stream().sorted() and returns a new sorted map. A Set uses new TreeSet or a sorted stream
Arrays and lists are sorted in place. Streams, maps and sets give a new sorted object.

The examples sort a small playlist in which each song is a Song record (a short way to write an immutable data class). The natural order of a Song is its title.

record Song(String title, String artist, int year, int plays) implements Comparable<Song> {

  @Override
  public int compareTo(Song other) {
    return this.title.compareTo(other.title);
  }
}

List<Song> songs = new ArrayList<>(List.of(
    new Song("Rain", "Ben", 2021, 300),
    new Song("Blue", "Ava", 2019, 120),
    new Song("Echo", "Ava", 2023, 450),
    new Song("Sun", "Ben", 2019, 80)));

The result comments show only the song titles, because the example class overrides toString() to print the title.

2. Comparable vs Comparator

To sort, Java compares two elements at a time and decides which one comes first. Java gets the answer from one of two interfaces.

  • Comparable is implemented by the class itself. Its compareTo() method defines the natural order, the one default order of the class. For example, String values go in alphabetical order, and LocalDate values go from the oldest date to the newest.
  • Comparator is a separate object that we pass to the sort method. It defines any extra order, such as “by plays, highest first”, without changing the class.

Both methods return a number that tells the order. A negative number means the first element comes first, and a positive number means the second element comes first. Zero means both elements are equal.

ComparableComparator
Packagejava.langjava.util
MethodcompareTo(T other)compare(T a, T b)
Where it is definedInside the class being sortedIn a separate object, often a lambda
How many ordersOne (the natural order)Any number
Used byCollections.sort(list), Arrays.sort(a), sorted(), TreeMap, TreeSetlist.sort(c), Arrays.sort(a, c), sorted(c), new TreeMap<>(c)
Works for classes we cannot changeNoYes (String, JDK classes, library classes)

We implement Comparable only when a class has one obvious order, and for every other order we write a Comparator, often next to a Comparable class.

2.1. Sorting by the Natural Order

A class that implements Comparable needs no extra argument. The methods Collections.sort() and list.sort(null) call compareTo(), and so does sorted() on a stream.

Collections.sort(songs);                     // [Blue, Echo, Rain, Sun]
songs.sort(null);                            // same result, null means natural order
List<Song> copy = songs.stream().sorted().toList();

When a class does not implement Comparable, Collections.sort(list) does not compile for that class. The calls list.sort(null) and stream.sorted() do compile, but they throw a ClassCastException at runtime.

2.2. Building a Comparator with comparing() and thenComparing()

Since Java 8, we rarely write a Comparator class by hand. Instead, we call Comparator.comparing() and pass it a key extractor (a function that reads the field to compare, such as the plays count), and it returns a ready Comparator. A lambda expression or a method reference such as Song::plays can serve as the key extractor.

songs.sort(Comparator.comparingInt(Song::plays));                 // [Sun, Blue, Rain, Echo]
songs.sort(Comparator.comparing(Song::plays).reversed());         // [Echo, Rain, Blue, Sun]

songs.sort(Comparator.comparing(Song::artist)
    .thenComparing(Song::plays, Comparator.reverseOrder()));      // [Echo, Blue, Rain, Sun]

songs.sort(Comparator.comparing(Song::year).reversed()
    .thenComparing(Song::title));                                 // [Echo, Rain, Blue, Sun]

Comparator<Song> byArtist = (a, b) -> a.artist().compareTo(b.artist());   // lambda form

Each call returns a new Comparator, so we chain the calls and read the chain from left to right, with the most important sort key first.

MethodWhat it does
comparing(Song::artist)Compares by one field that is Comparable
comparingInt(Song::plays)Same, for an int field. Skips wrapping each value in an Integer object
thenComparing(Song::year)Breaks ties. Runs only when the previous comparison returns 0
thenComparing(Song::plays, Comparator.reverseOrder())Breaks ties with its own order, here descending
reversed()Reverses the whole comparator built so far, not only the last field
Comparator.naturalOrder(), Comparator.reverseOrder()Natural order and its reverse, for Comparable types

The position of reversed() in a chain matters. The method reversed() reverses everything built before it, so comparing(Song::artist).thenComparing(Song::year).reversed() also sorts the artists from Z to A, and the result is [Rain, Sun, Echo, Blue].

To make only one field descending, we pass Comparator.reverseOrder() to thenComparing(), or we call reversed() before adding the next field. The same chains work when we sort on multiple fields of any class, and when we write the Comparator as a lambda.

2.3. Sorting Lists That Contain null

The natural order cannot compare null, so list.sort(Comparator.naturalOrder()) throws a NullPointerException when the list contains a null element. Comparator.nullsFirst() and Comparator.nullsLast() solve the problem, because each one wraps another comparator and puts the null elements at one end of the list.

List<String> withNull = Arrays.asList("pear", null, "fig");
withNull.sort(Comparator.naturalOrder());                         // NullPointerException
withNull.sort(Comparator.nullsFirst(Comparator.naturalOrder()));  // [null, fig, pear]
withNull.sort(Comparator.nullsLast(Comparator.naturalOrder()));   // [fig, pear, null]

// null fields inside objects
songs.sort(Comparator.comparing(Song::artist, Comparator.nullsLast(Comparator.naturalOrder())));

The same wrappers work inside sorted() when we sort a stream with null values.

3. Sorting Arrays

The java.util.Arrays class has one sort() method for each primitive type, such as int or double, and two sort() methods for object arrays. All of them sort the array in place and return void, so we read the result from the same array.

3.1. Why an int[] Cannot Take a Comparator

A Comparator<T> works only with objects, because Java generics (the <T> part) accept only object types. An int[] holds primitive int values, not Integer objects, so no sort(int[], Comparator) method exists, and javac rejects the call with a “no suitable method found” error.

error: no suitable method found for sort(int[],Comparator<T#1>)
    method Arrays.<T#2>sort(T#2[],Comparator<? super T#2>) is not applicable
      (inference variable T#2 has incompatible bounds
        equality constraints: int
        upper bounds: Object)

For a primitive array in descending order, we sort ascending and then reverse, or we box the values into a stream. Boxing means wrapping each int in an Integer object, and an Integer[] array accepts a Comparator.

// Option 1: box, sort with a Comparator, unbox
int[] desc = IntStream.of(5, 3, 9, 1)
    .boxed()
    .sorted(Comparator.reverseOrder())
    .mapToInt(Integer::intValue)
    .toArray();                                    // [9, 5, 3, 1]

// Option 2: sort ascending, then swap from both ends (no boxing)
int[] numbers = {5, 3, 9, 1};
Arrays.sort(numbers);                              // [1, 3, 5, 9]
for (int i = 0, j = numbers.length - 1; i < j; i++, j--) {
  int tmp = numbers[i];
  numbers[i] = numbers[j];
  numbers[j] = tmp;
}                                                  // [9, 5, 3, 1]

// Object arrays take a Comparator
Integer[] boxed = {5, 3, 9, 1};
Arrays.sort(boxed, Comparator.reverseOrder());     // [9, 5, 3, 1]
Song[] songArray = songs.toArray(new Song[0]);
Arrays.sort(songArray, Comparator.comparingInt(Song::plays));   // [Sun, Blue, Rain, Echo]

Option 1 creates one Integer object per element, and on large arrays those objects cost memory, so option 2 is the faster choice there. Any other way to reverse an array also works after the ascending sort.

The two kinds of arrays also use different sorting algorithms, and only the object arrays get a stable sort.

Array typeAlgorithm in JDK 25Stable?Comparator
int[], long[], double[], char[] and other primitivesDual-Pivot QuicksortDoes not matter (two equal int values look the same)No
Object[], Integer[], String[], Song[]TimSort (a merge sort that runs faster on partly sorted data)YesYes

3.2. Sorting Part of an Array

Arrays.sort(a, fromIndex, toIndex) sorts only the part of the array that starts at fromIndex (included) and stops before toIndex (excluded), so elements outside the part keep their positions.

int[] range = {9, 7, 5, 3, 1, 0};
Arrays.sort(range, 1, 4);                          // [9, 3, 5, 7, 1, 0], indexes 1 to 3 sorted

String[] words = {"fig", "pear", "apple", "kiwi"};
Arrays.sort(words, 0, 2, Comparator.reverseOrder());   // [pear, fig, apple, kiwi]

An index outside the array throws ArrayIndexOutOfBoundsException, and a fromIndex larger than toIndex throws IllegalArgumentException: fromIndex(4) > toIndex(2).

3.3. Arrays.parallelSort() for Large Arrays

Arrays.parallelSort() splits a large array into parts, lets several threads sort the parts at the same time, and then merges the results. The threads come from the common ForkJoinPool, a shared pool of worker threads in the JDK. The method parallelSort() has the same versions as sort(), including a range and a Comparator, and gives the same result.

int[] big = new Random(42).ints(1_000_000, 0, 1000).toArray();
int[] copy = big.clone();
Arrays.parallelSort(big);
Arrays.sort(copy);
boolean same = Arrays.equals(big, copy);                     // true

String[] words = {"pear", "fig", "apple"};
Arrays.parallelSort(words, Comparator.reverseOrder());       // [pear, fig, apple]

The method parallelSort() does not always run in parallel. In the JDK 25 source, the method sorts on one thread when the array is small, which means up to 4,096 elements for primitive arrays and 8,192 for object arrays, and also when the machine has only one core for the pool.

Parallel sorting is faster only for large arrays, and the method shares the common pool with parallel streams, so we measure with real data before switching.

4. Sorting a List

A List has three sort options. Collections.sort(list) and Collections.sort(list, c) have existed since Java 1.2, and since Java 8 the Collections.sort() methods call list.sort(), so list.sort() does the same work, called on the list itself.

List<String> names = new ArrayList<>(List.of("Lokesh", "Alex", "John"));

// in place
Collections.sort(names);                             // [Alex, John, Lokesh]
names.sort(Comparator.reverseOrder());               // [Lokesh, John, Alex]
names.sort(null);                                    // [Alex, John, Lokesh], natural order

// new list, the source keeps its order
List<String> source = new ArrayList<>(List.of("Lokesh", "Alex", "John"));
List<String> copy = source.stream().sorted().toList();  // copy = [Alex, John, Lokesh]
                                                         // source = [Lokesh, Alex, John]

We use list.sort() when the list itself should change, for example to sort an ArrayList in ascending or descending order. We use stream().sorted() when the original order must stay, or when sorting a stream is one step in a pipeline next to filter() and map().

An unmodifiable list (a list that cannot be changed) cannot be sorted in place. The methods List.of(), Stream.toList() and Collections.unmodifiableList() return unmodifiable lists, and sort() on them throws UnsupportedOperationException.

List.of("b", "a").sort(null);                        // UnsupportedOperationException
Stream.of("b", "a").toList().sort(null);             // UnsupportedOperationException
new ArrayList<>(List.of("b", "a")).sort(null);       // OK: [a, b]

Arrays.asList() is a special case. The list has a fixed size, so we cannot add or remove elements, but it allows set(), so sort() works on it, whereas add() throws an UnsupportedOperationException.

5. Sorting a Map by Key or by Value

A HashMap keeps no order, so “sorting a map” means copying the entries into a map type that keeps an order. A TreeMap keeps its keys sorted, whereas a LinkedHashMap keeps the order in which the entries were added. For example, a team page that reads member ages from a HashMap shows the names in hash order until we copy the entries into one of the two ordered maps.

Map<String, Integer> ages = Map.of("Lokesh", 37, "John", 40, "Alex", 25);

// 1. By key: TreeMap sorts the keys
Map<String, Integer> byKey = new TreeMap<>(ages);              // {Alex=25, John=40, Lokesh=37}

Map<String, Integer> byKeyDesc = new TreeMap<>(Comparator.reverseOrder());
byKeyDesc.putAll(ages);                                        // {Lokesh=37, John=40, Alex=25}

// 2. By value: sort the entries, collect into a LinkedHashMap
Map<String, Integer> byValue = ages.entrySet().stream()
    .sorted(Map.Entry.comparingByValue())
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
        (a, b) -> a, LinkedHashMap::new));                     // {Alex=25, Lokesh=37, John=40}

Map<String, Integer> byValueDesc = ages.entrySet().stream()
    .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
        (a, b) -> a, LinkedHashMap::new));                     // {John=40, Lokesh=37, Alex=25}

The four-argument toMap() matters, because its fourth argument, LinkedHashMap::new, tells the collector which map to create. The two-argument Collectors.toMap() returns a HashMap and loses the sorted order. With the two-argument version, the same stream prints {Alex=25, John=40, Lokesh=37} instead of the value order.

The call Map.Entry.<String, Integer>comparingByValue() names the types on purpose, because Java cannot work out the generic types on its own before reversed(). We use the same two patterns to sort a map by keys or to sort a map by values with any other comparator. Of the Java Map classes, only the ordered ones keep the result of the sort.

6. Keeping Data Sorted with TreeSet and TreeMap

When elements arrive over time, sorting a list again after each insert wastes work. Say a music app shows the genre tags of a playlist in order, and users add tags one at a time. A TreeSet or a TreeMap keeps its content sorted on every insert instead, and each insert takes O(log n) time, so the cost grows slowly as the collection grows. Both classes also offer range methods, such as headSet().

TreeSet<String> tags = new TreeSet<>(List.of("rock", "jazz", "pop", "jazz"));
                                       // [jazz, pop, rock], the duplicate jazz is dropped
String first = tags.first();           // jazz
String last = tags.last();             // rock
SortedSet<String> before = tags.headSet("pop");   // [jazz], elements before "pop"

A TreeSet uses the comparator, not equals(), to decide whether two elements are duplicates. When the comparator returns 0, the TreeSet treats the new element as a duplicate and drops it, so a comparator that compares only one field drops elements without any error. In the example, Echo has the same artist as Blue, and Sun has the same artist as Rain.

TreeSet<Song> byArtist = new TreeSet<>(Comparator.comparing(Song::artist));
byArtist.addAll(songs);                // [Blue, Rain], size 2: Echo and Sun were dropped

TreeSet<Song> byArtistTitle = new TreeSet<>(
    Comparator.comparing(Song::artist).thenComparing(Song::title));
byArtistTitle.addAll(songs);           // [Blue, Echo, Rain, Sun], size 4

The same rule applies to TreeMap keys. A PriorityQueue (a queue that always returns the smallest element first) takes the same comparators, but a loop over a PriorityQueue does not see the elements in sorted order.

7. Sorting Strings

The natural order of String compares the UTF-16 code of each character, which is the number that UTF-16 gives that character. All uppercase letters come before all lowercase letters, so “Bea” sorts before “alex”, and for lists that people read, we want another order.

7.1. Case-Insensitive Sorting

String.CASE_INSENSITIVE_ORDER is a ready Comparator that ignores case, using the same rule as compareToIgnoreCase(). A contact list is a typical case, because users type names in any case and still expect “alex” next to “Alice”.

List<String> names = new ArrayList<>(List.of("bob", "Alice", "alex", "Bea"));
names.sort(null);                                  // [Alice, Bea, alex, bob]
names.sort(String.CASE_INSENSITIVE_ORDER);         // [alex, Alice, Bea, bob]
names.sort(Comparator.comparing(String::length)
    .thenComparing(String.CASE_INSENSITIVE_ORDER)); // [Bea, bob, alex, Alice]

The same comparators sort a String array in alphabetical order, and they also sort the characters of one String alphabetically.

7.2. Locale-Aware Sorting with Collator

The natural order and the case-insensitive order both sort accented letters in the wrong place. Take the letter e with an acute accent, written \u00e9 as a Java escape. Its code is higher than the code of every ASCII letter, so the natural order puts “\u00e9clair” after “zebra”. A java.text.Collator fixes the order, because it compares strings by the rules of a language, and it is itself a Comparator.

List<String> words = new ArrayList<>(List.of("zebra", "\u00e9clair", "eclair", "Apple"));
words.sort(null);                                  // [Apple, eclair, zebra, \u00e9clair]
words.sort(Collator.getInstance(Locale.FRENCH));   // [Apple, eclair, \u00e9clair, zebra]

Collator collator = Collator.getInstance(Locale.ENGLISH);
collator.setStrength(Collator.PRIMARY);            // ignore case and accents
int primary = collator.compare("eclair", "\u00c9clair");   // 0, equal
int natural = "eclair".compareTo("\u00c9clair");          // -100

We use a Collator whenever the sorted text is shown to users in a language other than plain English. The strength setting decides which differences count.

  • Collator.PRIMARY compares base letters only.
  • Collator.SECONDARY also compares accents.
  • Collator.TERTIARY, the default, also compares case.

8. Is Sorting in Java Stable?

Yes for object arrays and lists, and ordered streams sort stably too. A stable sort keeps equal elements in the order they already had, which lets us sort in two passes, first by the secondary field and then by the main field. In the example, the first sort orders the songs by plays, and the second sort groups them by artist while the plays order stays inside each artist.

songs.sort(Comparator.comparingInt(Song::plays).reversed());   // [Echo, Rain, Blue, Sun]
songs.sort(Comparator.comparing(Song::artist));                // [Echo, Blue, Rain, Sun]
Two columns of songs. Left, sorted by plays, highest first: Echo Ava 450, Rain Ben 300, Blue Ava 120, Sun Ben 80. Right, after a second sort by artist: Echo, Blue, Rain, Sun. Inside each artist, the plays order from the first sort is kept
After the second sort, the songs of each artist are still ordered by plays. The sort is stable.

The Javadoc promises a stable sort for each of these methods, so a two-pass sort works with any of them.

  • Arrays.sort(Object[]), Arrays.sort(T[], Comparator) and Arrays.parallelSort() for object arrays
  • Collections.sort() and the default List.sort() implementation
  • Stream.sorted() on ordered streams, such as streams from a List. Unordered streams, such as HashSet.stream(), have no such promise.

A chained comparator such as comparing(Song::artist).thenComparing(…) gives the same result in one pass and is easier to read. So the two-pass style is mostly useful when the sort keys are chosen at runtime, for example in a table where the user clicks columns to sort.

9. Common Sorting Mistakes

Most sorting bugs give a wrong order without any exception, and four mistakes come up again and again in code reviews.

9.1. Subtracting Values in compare()

Never write return a – b; in a comparator. For large values with opposite signs, the subtraction overflows, because the result does not fit in an int, so the value wraps around and gets the wrong sign.

List<Integer> values = new ArrayList<>(List.of(-2_000_000_000, 2_000_000_000, 0));
values.sort((a, b) -> a - b);           // [0, 2000000000, -2000000000], wrong
int diff = -2_000_000_000 - 2_000_000_000;   // 294967296, positive instead of negative
values.sort(Integer::compare);          // [-2000000000, 0, 2000000000], correct

We use Integer.compare(), Long.compare(), Double.compare() or Comparator.comparingInt() instead, and the same rule applies to compareTo() methods written as this.id – other.id.

9.2. Calling reversed() at the End of a Chain

The method reversed() reverses everything before it, as we saw in section 2.2. So a chain such as comparing(Song::artist).thenComparing(Song::year).reversed() reverses the artist order too. To make one field descending, we pass Comparator.reverseOrder() to that field only.

9.3. Sorting a List.of() or toList() Result

List.of() and Stream.toList() return unmodifiable lists, so calling sort() on them throws UnsupportedOperationException. We copy the elements into an ArrayList first, or we sort inside the stream with sorted() before toList().

9.4. Comparators That Break the Contract

A comparator must follow a few rules, called its contract. If a < b and b < c, then a < c must hold as well, and compare(a, b) must have the opposite sign of compare(b, a). Comparators in real code break the contract in a few typical ways.

  • The comparator never returns 0.
  • The comparator mixes up the signs.
  • The comparator reads a field that changes during the sort.

For example, a comparator that never returns 0 fails on a list of 10,000 random numbers.

many.sort((x, y) -> x < y ? -1 : 1);    // 10,000 random numbers between 0 and 99
// IllegalArgumentException: Comparison method violates its general contract!

TimSort detects some broken comparators and throws the IllegalArgumentException, but in the other cases the order is wrong and no error appears. Comparators built with comparing() and thenComparing() avoid the problem.

10. Sorting in Java FAQs

10.1. How Do We Sort in Descending Order in Java?

For the natural order, we pass Comparator.reverseOrder(), and for a custom comparator, we call reversed() on it. Primitive arrays need the workarounds from section 3.1.

names.sort(Comparator.reverseOrder());
songs.sort(Comparator.comparingInt(Song::plays).reversed());
Integer[] boxed = {5, 3, 9, 1};
Arrays.sort(boxed, Collections.reverseOrder());    // [9, 5, 3, 1], same as Comparator.reverseOrder()

10.2. Which Algorithm Does Arrays.sort() Use and What Is Its Time Complexity?

Arrays.sort() uses Dual-Pivot Quicksort for primitive arrays, and TimSort for object arrays and lists. Both run in O(n log n) time, so the work grows a little faster than the number of elements. TimSort needs far fewer comparisons when the input is already partly sorted. Dual-Pivot Quicksort is a variant of quicksort, and TimSort builds on merge sort.

10.3. How Do We Sort a Set in Java?

A HashSet has no order, so we copy its elements either into a TreeSet, which is sorted and has no duplicates, or into a sorted list.

Set<String> tags = new HashSet<>(Set.of("rock", "jazz", "pop"));
TreeSet<String> sortedSet = new TreeSet<>(tags);              // [jazz, pop, rock]
List<String> sortedList = tags.stream().sorted().toList();    // [jazz, pop, rock]

10.4. How Do We Check Whether an Array or List Is Already Sorted?

The JDK has no isSorted() method, so we compare the elements ourselves. To check whether an array is sorted, we compare each element with its neighbor, using either a loop or a stream. The same comparator logic works for a List.

11. Conclusion

For most code, list.sort(Comparator.comparing(…)) and Arrays.sort() sort the data in place, and stream().sorted() sorts inside a pipeline. Comparable defines the one natural order of a class, and Comparator chains define every other order, including descending fields and null handling.

To sort a map by key, we copy the map into a TreeMap, and to sort by value, we collect the sorted entries into a LinkedHashMap. A Collator handles text in human languages, and stability makes two-pass sorts predictable. Finally, Integer.compare() instead of subtraction avoids the overflow bug.

12. References

Happy Learning !!

Source Code on Github

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.