Как отсортировать карту - PullRequest
1 голос
/ 29 марта 2012

У меня есть карта для сортировки следующим образом:

Map<String, String> map = new HashMap(); 

Содержит следующие строковые ключи:

String key = "key1.key2.key3.key4" 

Содержит следующие строковые значения:

String value = "value1.value2"

, где ключ и значение могут варьироваться в зависимости от количества секций точек от key1 / value1 до key1.key2.key3.key4.key5 / value1.value2.value3.value4.value5 неоднородно

Мне нужно сравнить их в соответствии с количеством точек, присутствующих в ключах или в значениях в соответствии с типом вызывающего метода key / значение :

sortMap(Map map, int byKey);

или

sortMap(Map map, int byValue);

Методы, конечно, вернут отсортированную карту.

Любая помощь будетбыть оцененным.

Ответы [ 4 ]

4 голосов
/ 29 марта 2012

Невозможно наложить какой-либо порядок на HashMap.

. Если вы хотите упорядочить элементы путем некоторого сравнения клавиш, используйте TreeMap снекоторые Comparator на клавишах или просто использовать их по умолчанию Comparable упорядочение.

Если вы хотите упорядочить по значениям, единственная реальная опцияиспользовать LinkedHashMap, который сохраняет порядок, в котором записи были размещены на карте, а затем отсортировать записи перед вставкой их в карту, или, возможно, некоторую не-JDK Map реализацию.Есть грязные хаки, которые делают ключевой компаратор, который фактически тайно сравнивает значения, но они опасны и часто приводят к непредсказуемому поведению.

1 голос
/ 29 марта 2012

Вы должны использовать TreeMap и реализовать ValueComparator или сделать объекты ключа и значения, которые реализуют Comparable.

Должен быть здесь дубликатом ...

edit: дубликат (для именитолько один) Сортировать картупо значениям (Java)

1 голос
/ 29 марта 2012

Для начала вам нужно будет использовать экземпляр SortedMap. Если карта не реализует этот интерфейс, то она имеет неопределенный / произвольный порядок итераций, и вы не можете управлять им. (Как правило, это так, поскольку карта - это способ связывания значений с ключами; упорядочение является вспомогательной задачей.)

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

Это, однако, будет работать только при сортировке по ключу. Я не знаю, имеет ли смысл сортировать карту по значению, и я не знаю ни одного простого способа сделать это. Лучшее, что я могу придумать, это написать Comparator<Map.Entry>, который сортирует по значениям, вызвать Map.getEntrySet и поместить все записи в список, а затем вызвать Collections.sort в списке. Он не очень элегантный или эффективный, но он должен выполнять свою работу, если производительность не является вашей главной задачей.

(Обратите также внимание, что если ваши ключи не являются неизменяемыми, вы столкнетесь с большим количеством проблем, поскольку они не будут восстановлены при внешнем изменении.

0 голосов
/ 29 марта 2012

Я сделал это следующим образом:

@SuppressWarnings({ "unchecked", "rawtypes" })
public static Map sortMap(Map unsortedMap) {

    List list = new LinkedList(unsortedMap.entrySet());
    // sort list based on comparator
    Collections.sort(list, new Comparator() {
        public int compare(Object o1, Object o2) {
            String value1 = (String)((Map.Entry) (o1)).getValue();
            String value2 = (String)((Map.Entry) (o2)).getValue();
            // declare the count
            int count1 = findOccurances(value1, '.');
            int count2 = findOccurances(value2, '.');
            // Go to thru the comparing
            if(count1 > count2){
                return -1;
            }
            if(count1 < count2){
                return 1;
            }
            return 0;
        }
    });

    // put the sorted list into map again
    Map sortedMap = new LinkedHashMap();
    for (Iterator it = list.iterator(); it.hasNext();) {
        Map.Entry entry = (Map.Entry) it.next();
        sortedMap.put(entry.getKey(), entry.getValue());
    }
    return sortedMap;
}

С помощью следующего вспомогательного метода:

private static int findOccurances(String s, char chr) {
    final char[] chars = s.toCharArray();
    int count = 0;
    for (int i = 0; i < chars.length; i++) {
        if (chars[i] == chr) {
            count++;
        }
    }
    return count;
}

Здесь я могу добавить немного switch в сравнительную часть с дополнительнымint аргумент для изменения между asc / desc .

Я могу переключаться между значениями и ключами с помощью switch другого int значения аргумента, чтобы получить мой ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...