Алфавитная сортировка довольно медленно - PullRequest
0 голосов
/ 29 августа 2018

Вот моя проблема: у меня есть список пользовательских объектов, которые содержат строку с именем label. Этот список большой, но слишком большой, около 1000 объектов. Я хотел бы сделать сортировку по алфавиту, используя label.

Дело в том, что некоторые label содержат такие символы, как, например, É, (, e или E в качестве первого символа. Поэтому мне пришлось использовать функцию deAccent() найденный здесь , чтобы отсортировать ее независимо от акцента или чего-то подобного. С помощью этой функции список ['Gab','eaaa','Éaa'] сортируется так: ['eaaa','Éaa','Gab'] вместо ['eaaa','Gab','Éaa']. Потому что когда мы используем метод compareTo, É идет после G. Вот что у меня есть:

private List<Formula> sortFormulaList(List<Formula> formulaList) {
    // Sort all label alphabetically
    if (formulaList.size() > 0) {
        Collections.sort(formulaList, (formula1, formula2) ->
                deAccent(formula1.getLabel()).toLowerCase().compareTo(deAccent(formula2.getLabel().toLowerCase())));
    }
    return formulaList;
}

private String deAccent(String str) {
    String nfdNormalizedString = Normalizer.normalize(str, Normalizer.Form.NFD);
    Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
    return pattern.matcher(nfdNormalizedString).replaceAll("");
}

Если я не использую deAccent(), это достаточно быстро для моей цели, но когда я использую его, то для сортировки требуется от 1 до 3 секунд.

Есть идеи о том, как я могу сделать такой вид? Или сделайте это быстрее

1 Ответ

0 голосов
/ 29 августа 2018

Рассмотрите превосходное предложение @ Генри, и Formula может выглядеть так:

public class Formula {
    private final String label;
    private final String deAccentedLabel;

    public Formula(String label) {
        this.label = label;
        this.deAccentedLabel = deAccent(label);
    }

    public String getLabel() {
        return label;
    }

    public String getDeAccentedLabel() {
        return comparableLabel;
    }


    private String deAccent(String str) {
        String nfdNormalizedString = Normalizer.normalize(str, Normalizer.Form.NFD);
        Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
        return pattern.matcher(nfdNormalizedString).replaceAll("");
    }

}

Тогда его можно использовать так:

Collections.sort(formulaList, (formula1, formula2) -> formula1.getDeAccentedLabel().toLowerCase().compareTo(formula2.getDeAccentedLabel().toLowerCase());

Однако это предоставляет deAccentedLabel путем добавления метода public getDeAccentedLabel().

В комментарии я предлагал скрыть deAccentedLabel, чтобы сохранить общедоступный интерфейс Formula как можно более чистым. Таким образом, для сортировки Formula предоставляет компаратор вместо других классов, которые его собирают . Formula будет выглядеть примерно так:

public class Formula {
    private final String label;
    private final String comparableLabel;

    public Formula(String label) {
        this.label = label;
        this.comparableLabel = deAccent(label).toLowerCase();
    }

    public String getLabel() {
        return label;
    }

    private String deAccent(String str) {
        String nfdNormalizedString = Normalizer.normalize(str, Normalizer.Form.NFD);
        Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
        return pattern.matcher(nfdNormalizedString).replaceAll("");
    }

    public static Comparator<Formula> getLabelComparator() {
        return (formula1, formula2) -> formula1.comparableLabel.compareTo(formula2.comparableLabel);
    }

}

и используется так:

Collections.sort(formulaList, Formula.getLabelComparator());
...