2012-01-25 2 views
1

У меня есть следующие карты:Как отсортировать карту по значению (ArrayList) в Java?

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

, которая заполнена парами ключей и значений.
Например: key = имя студента и значение = фамилии членов семьи.
Я хочу отсортировать карту по размеру списка. Я попытался реализовать Компаратор с TreeMap, но у меня есть ошибка, поэтому я переключился на HashMap. Есть идеи?

+0

'TreeMap' with Comparator - это путь IMO .. Какая у вас была ошибка? – paislee

+0

Чтобы укрепить сообщение других ответов, вы не можете сортировать HashMap (или, вообще говоря, карту). Вам придется использовать определенные версии Карты, которые поддерживают сортировку. TreeMap кажется лучшим снимком для сортировки по значениям. – madth3

+0

TreeMap сортирует ключ, а не значение. –

ответ

3

Вы должны использовать HashMap неупорядоченный, а затем каждый раз, когда вы хотите заказать, поместите все значения HashMap в TreeMap, используя Comparator, который имеет HashMap в качестве переменной.

Затем для каждого ключа, который вы сравниваете, вы получаете значение HashMap (список) и проверяете размер списка. Таким образом, вы сравниваете размеры списка, возвращая -1, 0 или 1 в зависимости от случая.

Как только вы закончите то, что вам нужно, вы выбросите этот TreeMap.

Если вы попытаетесь использовать только TreeMap, то увидите, что вы заказываете ключи в соответствии со значением, которое не является свойством такого ключа. В этом случае длина значения (список). Таким образом, может существовать функция, которая увеличивает длину списка, и TreeMap даже не заметит.

Некоторый код:

public class ListSizeComparator implements Comparator<String> { 

private final Map<String, List<String>> map; 

public ListSizeComparator(final Map<String, List<String>> map) { 
    this.map = map; 
} 

@Override 
public int compare(String s1, String s2) { 
    //Here I assume both keys exist in the map. 
    List<String> list1 = this.map.get(s1); 
    List<String> list2 = this.map.get(s2); 
    Integer length1 = list1.size(); 
    Integer length2 = list2.size(); 
    return length1.compareTo(length2); 
} 

} 
+0

Я не уверен, что понимаю, что вы имеете в виду. Не могли бы вы рассказать о том, как будет выглядеть метод сравнения? – Johny

+0

Я добавил образец кода, чтобы проиллюстрировать мою мысль. – Luciano

+0

Эй, спасибо!Я попробовал TreeMap > sorter = new TreeMap (новый ListSizeComparator (карта)); но это не сработало. Когда я пытаюсь распечатать карту, я ничего не получаю. – Johny

0

Я вижу три варианта здесь:

  1. Отсортировать карта содержимое каждый раз, когда вам нужно - если это не слишком часто, что это нормально.
  2. В дополнение к карте хранить другую вспомогательную структуру с желаемым заказом, например TreeMap<Integer, List<String>> (ключ - количество членов семьи, значение - список студентов).
  3. Возможно, вам не нужна ваша карта, как вы ее описали, и следующей карты будет достаточно: TreeMap<Integer, Map<String, List<String>>> (ключ - количество членов семьи, значение - часть вашей исходной карты, содержащая учащихся с количеством членов семьи, равная $ ключ).
+0

Я просто пробовал это, но это не работает, потому что если у двух учеников одинаковое количество членов семьи, будет вставлен только один из них. Я думаю, что ключи являются уникальными на карте. – Johny

+0

Да, ключи уникальны. Вот почему значения карты представляют собой списки в случае 2 и карты в случае 3, что позволяет хранить несколько аварий на одном и том же ключе на карте верхнего уровня. –

2

решение более или менее идентичны https://stackoverflow.com/a/8897384/869736, но все, что вам нужно сделать, это написать Comparator, сравнивающий списки по их длине.

Comparator<List<String>> lengthComparator = new Comparator<List<String>>() { 
    public int compare(List<String> a, List<String> b) { 
    return a.size() - b.size(); 
    // size() is always nonnegative, so this won't have crazy overflow bugs 
    } 
}; 

, а затем просто используйте изложенное там решение.

+0

Эй, спасибо! Но это означает, что я должен использовать библиотеки Guava, не так ли? – Johny

+0

Да, это так. Работать вокруг было бы гораздо менее приятным, но все же выполнимым с помощью LinkedHashMap в качестве вывода, Collections.reverseOrder вместо Ordering.reverse(), делая явную копию и сортировку, а не используя Ordering.sortedCopy() и кучу других вещи. –

+0

И, конечно, верно, что структура коллекций Guava очень полезна, и это лишь малая часть его возможностей. Вы можете найти wiki (http://code.google.com/p/guava-libraries/wiki/GuavaExplained) полезным. –