Java сортирует строковый массив имен файлов по их расширению

StackOverflow https://stackoverflow.com/questions/440430

Вопрос

У меня есть массив имен файлов, и мне нужно отсортировать этот массив по расширениям имени файла. Есть ли простой способ сделать это?

Это было полезно?

Решение

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;
        }
    }
});

Для полноты картины: java.util.Arrays и java.util.Comparator .

Другие советы

Если я правильно помню, Arrays.sort (...) использует Comparator < > что он будет использовать для сортировки. Вы можете предоставить реализацию, которая смотрит на часть расширения строки.

Вы можете создать собственный компаратор Струн. Сделайте так, чтобы они сортировали их по подстроке после последнего индекса '.'. Затем передайте компаратор и ваш массив в

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('.'));
}

Компараторы часто трудно получить точно правильно, и ключ сравнения должен генерироваться для каждого сравнения, которое для большинства алгоритмов сортировки означает O (n log n). Другой подход заключается в создании пар (ключ, значение) для каждого элемента, который необходимо отсортировать, поместить их в TreeMap, а затем запросить значения, поскольку они отсортированы по ключу.

Например,

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());
    }
}

распечатывает

[#1, #2, #3]

Вы легко сможете адаптировать вычисления ключа к своей проблеме.

Это вычисляет ключ только один раз для каждой записи, следовательно, O (n) - (но сортировка по-прежнему O (n log n)). Если вычисление ключа дорого или n велико, это может быть вполне измеримо.

Создайте компаратор и сравните расширения строк. Посмотрите на следующее

http: //java.sun .com / J2SE / 1.4.2 / документы / API / Java / Util / Comparator.html

Затем передайте свой список строк в Arrays.sort (список, компаратор)

Создайте свой собственный компаратор который обрабатывает строки как имена файлов и сравнивает их на основе расширений. Затем используйте Arrays.sort с аргумент компаратора.

    String DELIMETER = File.separator + ".";
    List<String> orginalList = new CopyOnWriteArrayList<>(Arrays.asList(listOfFileNames));
    Set<String> setOfuniqueExtension = new TreeSet<>();

    for (String item : listOfFileNames) {
        if (item.contains(".")) {
            String[] split = item.split(DELIMETER);
            String temp = "." + split[split.length - 1];
            setOfuniqueExtension.add(temp);
        }
    }

    List<String> finalListOfAllFiles = new LinkedList<>();
    setOfuniqueExtension.stream().forEach((s1) -> {
        for (int i = 0; i < orginalList.size(); i++) {
            if (orginalList.get(i).contains(s1)) {
                finalListOfAllFiles.add(orginalList.get(i));
                orginalList.remove(orginalList.get(i));
                i--;
            }
        }
    });

    orginalList.stream().filter((s1) -> (!finalListOfAllFiles.contains(s1))).forEach((s1) -> {
        finalListOfAllFiles.add(s1);
    });

    return finalListOfAllFiles;

Если вы просто хотите сгруппировать файлы по их расширению и не заботиться о фактическом алфавитном порядке, вы можете использовать это:

Я думаю, что самое простое, что вы можете сделать, это также работает, когда имя файла не имеет ". " это просто поменять имена и сравнить их.

Arrays.sort(ary, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        String r1 = new StringBuffer(o1).reverse().toString();
        String r2 = new StringBuffer(o2).reverse().toString();
        return r1.compareTo(r2);
    }
});

Жаль, что в Java-строке нет даже функции reverse ().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top