How do I sort entries of a map by its keys or values?

To sort the entries of a map by keys or values in Java, you can convert your Map to a Stream, sort it, and then collect it back into a Map.

Here’s an example of sorting by keys:

package org.kodejava.util;

import java.util.HashMap;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.stream.Collectors;

public class MapSortComparingByKey {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("Apple", 10);
        map.put("Orange", 20);
        map.put("Banana", 30);

        Map<String, Integer> sortedByKey = map.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue,
                        LinkedHashMap::new
                ));

        sortedByKey.forEach((key, value) -> System.out.println("Key: " + key + ", Value: " + value));
    }
}

Output:

Key: Apple, Value: 10
Key: Banana, Value: 30
Key: Orange, Value: 20

In the example map.entrySet().stream() creates a Stream consisting of the entries in the map. The sorted(Map.Entry.comparingByKey()) method sorts the entries based on keys. The sorted entries are collected back into a new LinkedHashMap (which maintains the order of its elements).

You can sort by values in a similar way:

package org.kodejava.util;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class MapSortComparingByValue {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("Apple", 10);
        map.put("Orange", 20);
        map.put("Banana", 30);

        Map<String, Integer> sortedByValue = map.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue,
                        LinkedHashMap::new
                ));

        sortedByValue.forEach((key, value) -> System.out.println("Key: " + key + ", Value: " + value));
    }
}

Output:

Key: Banana, Value: 30
Key: Orange, Value: 20
Key: Apple, Value: 10

In this example, sorted(Map.Entry.<String, Integer>comparingByValue().reversed()) sorts the entries based on values in descending order. The reversed() method is used to reverse the natural ordering. If you want to sort in ascending order, omit the reversed() call.

How do I use the List.sort() method?

The List.sort() method was introduced in Java 8. This method sorts the elements of the list on the basis of the given Comparator. If no comparator is provided, it will use the natural ordering of the elements (only if the elements are Comparable).

Let’s take a look at an example where we sort a list of integers in ascending order:

package org.kodejava.util;

import java.util.ArrayList;
import java.util.List;

public class ListSortExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(3);
        numbers.add(1);
        numbers.add(4);
        numbers.add(1);
        numbers.add(5);

        // Use sort() to sort the numbers in ascending order
        numbers.sort(null);

        System.out.println(numbers); 
    }
}

Outputs:

[1, 1, 3, 4, 5]

You can also pass a Comparator to List.sort(). Here’s an example where we sort a list of strings by their length:

package org.kodejava.util;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class ListSortOtherExample {
    public static void main(String[] args) {
        List<String> words = new ArrayList<>();
        words.add("rat");
        words.add("elephant");
        words.add("cat");
        words.add("mouse");

        // Comparator for comparing string lengths
        Comparator<String> lengthComparator = (s1, s2) -> s1.length() - s2.length();

        // Use sort() to sort the words by their length
        words.sort(lengthComparator);

        System.out.println(words);
    }
}

Outputs:

[rat, cat, mouse, elephant]

In this case, the Comparator is a lambda expression that computes the difference in length between two strings. The List.sort() method uses this Comparator to determine the ordering of the strings in the list.

How do I sort strings based on their length?

You can sort strings based on their length using the sort method combined with a custom comparator. In the code snippet below we are going to use the Arrays.sort() method. We pass an array of string to the sort() method and also a lambda expression as the custom comparator.

Here is how you’d do it in Java:

package org.kodejava.util;

import java.util.Arrays;

public class SortStringsExample {
    public static void main(String[] args) {
        String[] strings = {"Hello", "World", "Java", "is", "beautiful"};

        // Sort the array based on string length
        Arrays.sort(strings, (a, b) -> a.length() - b.length());

        // Print the sorted array
        Arrays.stream(strings).forEach(System.out::println);
    }
}

In this example, an array of strings is sorted in increasing order of their lengths. If you want to sort them in descending order, you can change the comparator to (a, b) -> b.length() - a.length().

The output of the code snippet above is:

is
Java
Hello
World
beautiful

How do I sort file names by their extension?

To sort file names by their extension, we can use the ExtensionFileComparator class from the Apache Commons IO library. This class provides a couple instances of comparator such as:

Comparator Description
EXTENSION_COMPARATOR Case sensitive extension comparator
EXTENSION_REVERSE Reverse case sensitive extension comparator
EXTENSION_INSENSITIVE_COMPARATOR Case insensitive extension comparator
EXTENSION_INSENSITIVE_REVERSE Reverse case insensitive extension comparator
EXTENSION_SYSTEM_COMPARATOR System sensitive extension comparator
EXTENSION_SYSTEM_REVERSE Reverse system sensitive path comparator

The following snippet shows you how to use the first two comparators listed above.

package org.kodejava.commons.io;

import org.apache.commons.io.FilenameUtils;

import static org.apache.commons.io.comparator.ExtensionFileComparator.*;

import java.io.File;
import java.util.Arrays;

public class FileSortByExtension {
    public static void main(String[] args) {
        File file = new File(".");

        // Excludes directory in the list
        File[] files = file.listFiles(File::isFile);

        if (files != null) {
            // Sort in ascending order.
            Arrays.sort(files, EXTENSION_COMPARATOR);
            FileSortByExtension.displayFileOrder(files);

            // Sort in descending order.
            Arrays.sort(files, EXTENSION_REVERSE);
            FileSortByExtension.displayFileOrder(files);
        }
    }

    private static void displayFileOrder(File[] files) {
        System.out.printf("%-20s | %s%n", "Name", "Ext");
        System.out.println("--------------------------------");
        for (File file : files) {
            System.out.printf("%-20s | %s%n", file.getName(),
                    FilenameUtils.getExtension(file.getName()));
        }
        System.out.println();
    }
}

The result of the code snippet:

Name                 | Ext
--------------------------------
README               | 
lipsum.doc           | doc
lipsum.docx          | docx
data.html            | html
contributors.txt     | txt
pom.xml              | xml

Name                 | Ext
--------------------------------
pom.xml              | xml
contributors.txt     | txt
data.html            | html
lipsum.docx          | docx
lipsum.doc           | doc
README               | 

Maven Dependencies

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.14.0</version>
</dependency>

Maven Central

How do I sort files and directories based on their size?

In this example, you will learn how to sort files and directories based on their size. Using the Apache Commons IO, we can utilize the SizeFileComparator class. This class provides some instances to sort file size such as:

Comparator Description
SIZE_COMPARATOR Size comparator instance – directories are treated as zero size
SIZE_REVERSE Reverse size comparator instance – directories are treated as zero size
SIZE_SUMDIR_COMPARATOR Size comparator instance which sums the size of a directory’s contents
SIZE_SUMDIR_REVERSE Reverse size comparator instance which sums the size of a directory’s contents

Now let’s jump to the code snippet below:

package org.kodejava.commons.io;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.util.Arrays;

import static org.apache.commons.io.comparator.SizeFileComparator.*;

public class FileSortBySize {
    public static void main(String[] args) {
        File dir = new File(".");
        File[] files = dir.listFiles();

        if (files != null) {
            // Sort files in ascending order based on file size.
            System.out.println("Ascending order.");
            Arrays.sort(files, SIZE_COMPARATOR);
            FileSortBySize.displayFileOrder(files, false);

            // Sort files in descending order based on file size
            System.out.println("Descending order.");
            Arrays.sort(files, SIZE_REVERSE);
            FileSortBySize.displayFileOrder(files, false);

            // Sort files in ascending order based on file / directory
            // size
            System.out.println("Ascending order with directories.");
            Arrays.sort(files, SIZE_SUMDIR_COMPARATOR);
            FileSortBySize.displayFileOrder(files, true);

            // Sort files in descending order based on file / directory
            // size
            System.out.println("Descending order with directories.");
            Arrays.sort(files, SIZE_SUMDIR_REVERSE);
            FileSortBySize.displayFileOrder(files, true);
        }
    }

    private static void displayFileOrder(File[] files, boolean displayDirectory) {
        for (File file : files) {
            if (!file.isDirectory()) {
                System.out.printf("%-25s - %s%n", file.getName(),
                        FileUtils.byteCountToDisplaySize(file.length()));
            } else if (displayDirectory) {
                long size = FileUtils.sizeOfDirectory(file);
                String friendlySize = FileUtils.byteCountToDisplaySize(size);
                System.out.printf("%-25s - %s%n", file.getName(),
                        friendlySize);
            }
        }
        System.out.println("------------------------------------");
    }
}

In the code snippet above we use a couple method from the FileUtils class such as the FileUtils.sizeOfDirectory() to calculate the size of a directory and FileUtils.byteCountToDisplaySize() to create human-readable file size.

The result of the code snippet:

Ascending order.
.editorconfig             - 389 bytes
kodejava.iml              - 868 bytes
pom.xml                   - 1 KB
------------------------------------
Descending order.
pom.xml                   - 1 KB
kodejava.iml              - 868 bytes
.editorconfig             - 389 bytes
------------------------------------
Ascending order with directories.
.editorconfig             - 389 bytes
src                       - 851 bytes
kodejava.iml              - 868 bytes
pom.xml                   - 1 KB
apache-commons-example    - 8 KB
hibernate-example         - 29 KB
.idea                     - 85 KB
------------------------------------
Descending order with directories.
.idea                     - 85 KB
hibernate-example         - 29 KB
apache-commons-example    - 8 KB
pom.xml                   - 1 KB
kodejava.iml              - 868 bytes
src                       - 851 bytes
.editorconfig             - 389 bytes

Maven Dependencies

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.14.0</version>
</dependency>

Maven Central