Сортировать карту <Key, Value> по значениям - PullRequest
1514 голосов
/ 21 сентября 2008

Я относительно новичок в Java, и часто обнаруживаю, что мне нужно отсортировать Map<Key, Value> по значениям.

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

Есть ли более простой способ?

Ответы [ 49 ]

0 голосов
/ 24 октября 2013

как карта неупорядочена Для сортировки мы можем сделать следующее

Map<String, String> map= new TreeMap<String, String>(unsortMap);

Следует отметить, что, в отличие от хэш-карты, древовидная карта гарантирует, что ее элементы будут отсортированы в порядке возрастания ключа.

0 голосов
/ 20 февраля 2017

Лучше всего конвертировать HashMap в TreeMap. TreeMap сортирует ключи самостоятельно. Если вы хотите отсортировать значения, чем быстрое исправление, вы можете переключать значения с помощью клавиш, если ваши значения не являются дубликатами.

0 голосов
/ 21 сентября 2008

Если ваши значения Map реализуют Comparable (например, String), это должно работать

Map<Object, String> map = new HashMap<Object, String>();
// Populate the Map
List<String> mapValues = new ArrayList<String>(map.values());
Collections.sort(mapValues);

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

Collections.sort(mapValues, comparable);
0 голосов
/ 23 сентября 2016

Мое решение - довольно простой подход с использованием в основном данных API. Мы используем функцию Карта , чтобы экспортировать ее содержимое как Установить с помощью метода entrySet () . Теперь у нас есть Set , содержащий Map.Entry объектов.

Хорошо, набор не несет заказ, но мы можем взять содержимое и поместить его в ArrayList . Теперь он имеет порядок random , но мы все равно его отсортируем.

Поскольку ArrayList является Collection , теперь мы используем метод Collections.sort () для наведения порядка в хаосе. Поскольку наши Map.Entry объекты не реализуют необходимый нам тип сравнения, мы предоставляем специальный Comparator .

.
public static void main(String[] args) {
    HashMap<String, String> map = new HashMap<>();
    map.put("Z", "E");
    map.put("G", "A");
    map.put("D", "C");
    map.put("E", null);
    map.put("O", "C");
    map.put("L", "D");
    map.put("Q", "B");
    map.put("A", "F");
    map.put(null, "X");
    MapEntryComparator mapEntryComparator = new MapEntryComparator();

    List<Entry<String,String>> entryList = new ArrayList<>(map.entrySet());
    Collections.sort(entryList, mapEntryComparator);

    for (Entry<String, String> entry : entryList) {
        System.out.println(entry.getKey() + " : " + entry.getValue());
    }

}
0 голосов
/ 15 января 2016
    static <K extends Comparable<? super K>, V extends Comparable<? super V>>
    Map sortByValueInDescendingOrder(final Map<K, V> map) {
        Map re = new TreeMap(new Comparator<K>() {
            @Override
            public int compare(K o1, K o2) {
                if (map.get(o1) == null || map.get(o2) == null) {
                    return -o1.compareTo(o2);
                }
                int result = -map.get(o1).compareTo(map.get(o2));
                if (result != 0) {
                    return result;
                }
                return -o1.compareTo(o2);
            }
        });
        re.putAll(map);
        return re;
    }
    @Test(timeout = 3000l, expected = Test.None.class)
    public void testSortByValueInDescendingOrder() {
        char[] arr = "googler".toCharArray();
        Map<Character, Integer> charToTimes = new HashMap();
        for (int i = 0; i < arr.length; i++) {
            Integer times = charToTimes.get(arr[i]);
            charToTimes.put(arr[i], times == null ? 1 : times + 1);
        }
        Map sortedByTimes = sortByValueInDescendingOrder(charToTimes);
        Assert.assertEquals(charToTimes.toString(), "{g=2, e=1, r=1, o=2, l=1}");
        Assert.assertEquals(sortedByTimes.toString(), "{o=2, g=2, r=1, l=1, e=1}");
        Assert.assertEquals(sortedByTimes.containsKey('a'), false);
        Assert.assertEquals(sortedByTimes.get('a'), null);
        Assert.assertEquals(sortedByTimes.get('g'), 2);
        Assert.assertEquals(sortedByTimes.equals(charToTimes), true);
    }
0 голосов
/ 29 августа 2012

Мы просто сортируем карту так же, как эта

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

    unsortedMap.put("E", "E Val");
    unsortedMap.put("F", "F Val");
    unsortedMap.put("H", "H Val");
    unsortedMap.put("B", "B Val");
    unsortedMap.put("C", "C Val");
    unsortedMap.put("A", "A Val");
    unsortedMap.put("G", "G Val");
    unsortedMap.put("D", "D Val");

    Map<String, String> sortedMap = new TreeMap<String, String>(unsortedMap);

    System.out.println("\nAfter sorting..");
    for (Map.Entry <String, String> mapEntry : sortedMap.entrySet()) {
        System.out.println(mapEntry.getKey() + " \t" + mapEntry.getValue());
0 голосов
/ 21 сентября 2008

Для сортировки по ключам я нашел лучшее решение с помощью TreeMap (я тоже постараюсь получить решение для сортировки по значениям):

public static void main(String[] args) {
    Map<String, String> unsorted = new HashMap<String, String>();
    unsorted.put("Cde", "Cde_Value");
    unsorted.put("Abc", "Abc_Value");
    unsorted.put("Bcd", "Bcd_Value");

    Comparator<String> comparer = new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.compareTo(o2);
        }};

    Map<String, String> sorted = new TreeMap<String, String>(comparer);
    sorted.putAll(unsorted);
    System.out.println(sorted);
}

Вывод будет:

{Abc = Abc_Value, Bcd = Bcd_Value, Cde = Cde_Value}

0 голосов
/ 21 сентября 2008

Использование java.util.TreeMap .

"Карта сортируется в соответствии с естественным порядком ее ключей или с помощью компаратора, предоставляемого во время создания карты, в зависимости от того, какой конструктор используется."

0 голосов
/ 21 сентября 2008

Хорошо, эта версия работает с двумя новыми объектами Map и двумя итерациями и сортирует по значениям. Надеюсь, все работает хорошо, хотя записи на карте должны быть зациклены дважды:

public static void main(String[] args) {
    Map<String, String> unsorted = new HashMap<String, String>();
    unsorted.put("Cde", "Cde_Value");
    unsorted.put("Abc", "Abc_Value");
    unsorted.put("Bcd", "Bcd_Value");

    Comparator<String> comparer = new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.compareTo(o2);
        }};

    System.out.println(sortByValue(unsorted, comparer));

}

public static <K, V> Map<K,V> sortByValue(Map<K, V> in, Comparator<? super V> compare) {
    Map<V, K> swapped = new TreeMap<V, K>(compare);
    for(Entry<K,V> entry: in.entrySet()) {
        if (entry.getValue() != null) {
            swapped.put(entry.getValue(), entry.getKey());
        }
    }
    LinkedHashMap<K, V> result = new LinkedHashMap<K, V>();
    for(Entry<V,K> entry: swapped.entrySet()) {
        if (entry.getValue() != null) {
            result.put(entry.getValue(), entry.getKey());
        }
    }
    return result;
}

Решение использует TreeMap с компаратором и сортирует все нулевые ключи и значения. Сначала для сортировки значений используется функция упорядочения из TreeMap, затем отсортированная карта используется для создания результата в виде LinkedHashMap, который сохраняет тот же порядок значений.

Greetz, GHad

...