Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java sort String array of file names by their extension

I have an array of filenames and need to sort that array by the extensions of the filename. Is there an easy way to do this?

like image 767
Adam Lerman Avatar asked Jan 13 '09 19:01

Adam Lerman


4 Answers

Arrays.sort(filenames, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        // the +1 is to avoid including the '.' in the extension and to avoid exceptions
        // EDIT:
        // We first need to make sure that either both files or neither file
        // has an extension (otherwise we'll end up comparing the extension of one
        // to the start of the other, or else throwing an exception)
        final int s1Dot = s1.lastIndexOf('.');
        final int s2Dot = s2.lastIndexOf('.');
        if ((s1Dot == -1) == (s2Dot == -1)) { // both or neither
            s1 = s1.substring(s1Dot + 1);
            s2 = s2.substring(s2Dot + 1);
            return s1.compareTo(s2);
        } else if (s1Dot == -1) { // only s2 has an extension, so s1 goes first
            return -1;
        } else { // only s1 has an extension, so s1 goes second
            return 1;
        }
    }
});

For completeness: java.util.Arrays and java.util.Comparator.

like image 167
Michael Myers Avatar answered Sep 28 '22 01:09

Michael Myers


If I remember correctly, the Arrays.sort(...) takes a Comparator<> that it will use to do the sorting. You can provide an implementation of it that looks at the extension part of the string.

like image 26
Matthew Brubaker Avatar answered Sep 27 '22 23:09

Matthew Brubaker


You can implement a custom Comparator of Strings. Make it sort them by the substring after the last index of '.'. Then pass in the comparator and your array into

Arrays.sort(stringArray, yourComparator);

//  An implementation of the compare method
public int compare(String o1, String o2) {
    return o1.substring(o1.lastIndexOf('.')).compareTo(o2.substring(o2.lastIndexOf('.'));
}
like image 22
jjnguy Avatar answered Sep 28 '22 01:09

jjnguy


Comparators are often hard to get exactly right, and the comparison key has to be generated for every comparison which for most sorting algorithms mean O(n log n). Another approach is to create (key, value) pairs for each item you need to sort, put them in a TreeMap, and then ask for the values as these are sorted according to the key.

For instance

import java.util.Arrays;
import java.util.TreeMap;

public class Bar {

    public static void main(String[] args) {
        TreeMap<String, String> m2 = new TreeMap<String, String>();
        for (String string : Arrays.asList(new String[] { "#3", "#2", "#1" })) {
            String key = string.substring(string.length() - 1);
            String value = string;
            m2.put(key, value);
        }
        System.out.println(m2.values());
    }
}

prints out

[#1, #2, #3]

You should easily be able to adapt the key calculation to your problem.

This only calculates the key once per entry, hence O(n) - (but the sort is still O(n log n)). If the key calculation is expensive or n is large this might be quite measurable.

like image 40
Thorbjørn Ravn Andersen Avatar answered Sep 28 '22 00:09

Thorbjørn Ravn Andersen