Использование собственного компаратора приводит к непоследовательному упорядочению - PullRequest
0 голосов
/ 20 января 2020

Я работаю с приложением Android и хочу распечатать ключи и значения HashMap определенным образом. Допустим, следующее содержимое HashMap:

11: 000010
12: 102643
24: 877
3: 990000
h: 6008770000
m: 0800

Я хочу распечатать ключи и значения HashMap таким образом, чтобы ключи с буквами печатались сначала по алфавиту, а затем по цифре c ключей в порядке возрастания:

h: 6008770000
m: 0800
3: 990000
11: 000010
12: 102643
24: 877

Сейчас я делаю следующее:

  1. Получите набор ключей и сохраните его в ArrayList

  2. Сортировка ArrayList с использованием компаратора

  3. Распечатка значений на карте с использованием отсортированного списка

Вот мой код:

List<String> keyList = new ArrayList<>(requestMap.keySet());
Collections.sort((keyList), comparator);
for(String key : keyList) {
    Log.d(key, requestMap.get(key));
}

Comparator<String> comparator = (o1, o2) -> {
    if (o1 == null) return -1;
    else if (o2 == null) return 1;

    if(TextUtils.isDigitsOnly(o1) && TextUtils.isDigitsOnly(o2)) {
        return Integer.compare(Integer.parseInt(o1), Integer.parseInt(o2));
    }

    if(!TextUtils.isDigitsOnly(o1)) {
        return -1;
    } else {
        return o1.compareTo(o2);
    }
};

Пока это работает, но в некоторых случаях я не получаю желаемый заказ. Например, для конкретной карты c я всегда получаю следующий результат:

3: 005000
4: 000000058985
12: 095508
22: 022
h: 6008770000
m: 0221
11: 000004
13: 0120
24: 877
25: 00
35: 77690088000000131D20077100000F
37: QWERTY123456
41: 00000003
42: 100000004000000
48: 456789123451       0000050201
60: 000001
61: 0201020000000045000000000300000000000015000102000000049770000000049770000000001659

Я сделал компаратор с идеей, что сначала нужно отсортировать строки по алфавиту, а затем строки с цифрами c , но сейчас я сомневаюсь, что мои логики c для компаратора верны. Кто-нибудь может указать мне правильное направление?

1 Ответ

1 голос
/ 20 января 2020
if(TextUtils.isDigitsOnly(o1) && TextUtils.isDigitsOnly(o2)) {
    return Integer.compare(Integer.parseInt(o1), Integer.parseInt(o2));
}

Таким образом, рассматривается случай, когда обе являются только цифрами.

if(!TextUtils.isDigitsOnly(o1)) {
    return -1;

Это тот случай, когда первая имеет не цифры. Это возврат -1, даже если у второго нет цифр. Когда у обоих нет цифр, мы должны сравнивать.

} else {
    return o1.compareTo(o2);

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

}

Итак, похоже, что вы, безусловно, хотите удалить !!

Вероятно, вам следует также охватить все случаи. Либо есть условие, следует ли вам покрывать регистр сравнения

!TextUtils.isDigitsOnly(o1) && !TextUtils.isDigitsOnly(o2)

или гнездо

if (TextUtils.isDigitsOnly(o1)) {
    if (TextUtils.isDigitsOnly(o2)) {
        ...
    } else {
        ...
    }
} else {
    if (TextUtils.isDigitsOnly(o2)) {
        ...
    } else {
        ...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...