Отсортировать карту по значению!

 
 
 
Сообщения:33
У меня есть Map<UUID, Integer> map которая хранит всех пользователей и их "баллы". Мне надо отсортировать такую карту так, чтоб Integer шли по убыванию..
Есть ли у кого готовое решение для такой задачки?
 
 
Сообщения:1402
http://stackoverflow.com/questions/109383/sort-a-mapkey-value-by-values-java
import java.util.*;

public class MapUtil
{
    public static <K, V extends Comparable<? super V>> Map<K, V> 
        sortByValue( Map<K, V> map )
    {
        List<Map.Entry<K, V>> list =
            new LinkedList<Map.Entry<K, V>>( map.entrySet() );
        Collections.sort( list, new Comparator<Map.Entry<K, V>>()
        {
            public int compare( Map.Entry<K, V> o1, Map.Entry<K, V> o2 )
            {
                return (o1.getValue()).compareTo( o2.getValue() );
            }
        } );

        Map<K, V> result = new LinkedHashMap<K, V>();
        for (Map.Entry<K, V> entry : list)
        {
            result.put( entry.getKey(), entry.getValue() );
        }
        return result;
    }
}

Но при очередном добавлении, она конечно перестанет быть сортированной по ключу
 
 
Сообщения:33
,Сделал вот такое решение, заменив Map<UUID, Ineger> на List<Pair<UUID, Integer>>, однако интересует, есть ли решение "элегантнее"?
public class Solution {

    public static void main(String[] args) throws Exception {
        for (Pair<UUID, Integer> pair : getSorted())
            System.out.println(pair.getKey() + " - " + pair.getValue());
    }
    
    public static List<Pair<UUID, Integer>> getSorted() {
        List<Pair<UUID, Integer>> list = new ArrayList();
        Random r = new Random();
        for (int i = 0; i < 10000; i++)
            list.add(new Pair(UUID.randomUUID(), r.nextInt(Integer.MAX_VALUE)));
        Collections.sort(list, new MyComparator());
        return list;
    }

    public static class MyComparator implements Comparator<Pair<UUID, Integer>> {

        @Override
        public int compare(Pair<UUID, Integer> o1, Pair<UUID, Integer> o2) {
            return o2.getValue() - o1.getValue();
        }
    }
}
 
 
Сообщения:33
loptop:
http://stackoverflow.com/questions/109383/sort-a-mapkey-value-by-values-java
import java.util.*;

public class MapUtil
{
    public static <K, V extends Comparable<? super V>> Map<K, V> 
        sortByValue( Map<K, V> map )
    {
        List<Map.Entry<K, V>> list =
            new LinkedList<Map.Entry<K, V>>( map.entrySet() );
        Collections.sort( list, new Comparator<Map.Entry<K, V>>()
        {
            public int compare( Map.Entry<K, V> o1, Map.Entry<K, V> o2 )
            {
                return (o1.getValue()).compareTo( o2.getValue() );
            }
        } );

        Map<K, V> result = new LinkedHashMap<K, V>();
        for (Map.Entry<K, V> entry : list)
        {
            result.put( entry.getKey(), entry.getValue() );
        }
        return result;
    }
}

Но при очередном добавлении, она конечно перестанет быть сортированной по ключу

Хм, большое спасибо, немного изменил этот код (так как он сортировал в порядке возрастания, а мне нужно в порядке убывания), и в итоге... Он работает почти в 200 раз быстрее чем мой :D
Спасибо!

(Дальше идет код, и замеры по времени)

public class Solution {

    public static void main(String[] args) throws Exception {
        long l1 = System.currentTimeMillis();
        for (Pair<UUID, Integer> pair : getList()) {
            System.out.println(pair.getKey() + " - " + pair.getValue());
        }
        long l2 = System.currentTimeMillis()-l1;
        System.out.println("=============");
        long l3 = System.currentTimeMillis();
        for (Map.Entry<UUID, Integer> entry : getMap().entrySet()) {
            System.out.println(entry.getKey() + " - " + entry.getValue());
        }
        long l4 = System.currentTimeMillis()-l3;
        System.out.println("=============");
        System.out.println("Первый метод = " + l2);
        System.out.println("Второй метод = " + l4);
    }

    public static List<Pair<UUID, Integer>> getList() {
        List<Pair<UUID, Integer>> list = new ArrayList();
        Random r = new Random();
        for (int i = 0; i < 10; i++)
            list.add(new Pair(UUID.randomUUID(), r.nextInt(Integer.MAX_VALUE)));
        Collections.sort(list, new MyComparator());
        return list;
    }

    public static class MyComparator implements Comparator<Pair<UUID, Integer>> {

        @Override
        public int compare(Pair<UUID, Integer> o1, Pair<UUID, Integer> o2) {
            return o2.getValue() - o1.getValue();
        }
    }

    public static Map<UUID, Integer> getMap() {
        Map<UUID, Integer> map = new HashMap();
        Random r = new Random();
        for (int i = 0; i < 10; i++)
            map.put(UUID.randomUUID(), r.nextInt(Integer.MAX_VALUE));
        return sortByValue(map);
    }

    public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
        List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet());
        Collections.sort( list, new Comparator<Map.Entry<K, V>>() {

            @Override
            public int compare( Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
                return (o2.getValue()).compareTo(o1.getValue());
            }});
        Map<K, V> result = new LinkedHashMap<K, V>();
        for (Map.Entry<K, V> entry : list) {
            result.put( entry.getKey(), entry.getValue() );
        }
        return result;
    }
}


65812050-8b2d-49d9-a3e4-bc54bac92447 - 1394129302
99bdc254-14d7-4223-aef9-ef38fca0d7c1 - 1387633917
6104cea8-f69a-4ece-b783-a6de7d578533 - 1382442087
eadc9dbb-d84c-4e52-80bc-a361d7b84afa - 1278828538
491c3f12-f9b6-4bf2-9470-0080dcaa60fe - 1117076661
fd3e55fd-5e80-4cc5-ba66-012ca40d6880 - 705748083
e9dc362f-9eea-4ed1-b761-8be442ddd2d0 - 630032787
8829081d-bc65-4339-8f45-92546c265a66 - 627019857
98d0d1a2-ec4a-44e6-92d8-b04f6fe9e01d - 426693781
22af2845-6b79-43b3-ab8a-1e6297940035 - 198289291
=============
097d1425-d1ab-4160-ba44-0bbc70ad4eb6 - 1674815013
d444ed4b-7c8b-4e74-93e4-8294ee7c2884 - 1637520080
d31c3cf4-9459-4418-b80d-4809862976f2 - 1584190944
84575fbd-6038-4bd1-9005-153395435c47 - 1528492816
4ce688dd-6f35-47ce-bd0d-98e1c601f44c - 1183863739
18b6683f-f2f3-4f85-aa99-f6a29d3370a3 - 729972333
9c3b9d93-2705-4019-bdba-e04f746e0347 - 541147922
e1ee14cd-75a5-44fa-9e6c-b5876ecabdaf - 534656407
3053386a-fb22-49c3-991f-18a00f271775 - 440480987
b935f121-65ff-4377-834c-c0576b9315df - 87975303
=============
Первый метод = 760
Второй метод = 4
Изменен:18 авг 2016 08:44
 
 
Сообщения:1402
Стоило упомянуть, что вам не нужна мапка, а нужна отсортированная коллекция(лучше вообще описать задачу, которую вы хотите решить) и во время замеров производительность не стоит включать в него время генерации и вывод в консоль
 
 
Сообщения:33
loptop:
Стоило упомянуть, что вам не нужна мапка, а нужна отсортированная коллекция(лучше вообще описать задачу, которую вы хотите решить) и во время замеров производительность не стоит включать в него время генерации и вывод в консоль

Насчет замеров да - как по идиотски я сделал :(
А насчет задачи...
Задача такова, есть пользователи (игроки), каждый игрок имеет уникальный идентификатор (UUID), и у каждого пользователя есть очки (ну или точнее варпоинты) которые выражены в Integer..
Я хочу вывести пользователю информацию о лучших пользователях!
И я хочу сделать такую систему, пользователь может выбрать страницу, и количество пользователей на странице.
т.е. например, если пользователь выберет 5 страницу, и количество 20, то мне надо получить всех пользователей (и их очки), с 80 по 100...
Как-то так..
 
 
Сообщения:1402
Почему бы в классе User не сделать поле score и уже сортировать по нему, с помощью Collections.sort(users, comparator);
 
 
Сообщения:33
loptop:
Почему бы в классе User не сделать поле score и уже сортировать по нему, с помощью Collections.sort(users, comparator);

Ну потому-что у меня нету класса User как такового... У меня вообще нету класса или чего-то еще связанного с пользователями, у меня есть только файлик, в котором хранятся UUID и значения там разные (пароль, очки, емейо, и т.д.)...
Если делать класс для каждого пользователя и хранить его всегда в памяти (или даже иногда доставать), мне кажется слишком много оперативы брать может...
 
 
Сообщения:1402
Добавьте в свой проект миниБД, тот же sqllite, тогда вы сможете вытаскивать пользователей и сортировать их одним запросом, например
SELECT * FROM User ORDER BY score desc LIMIT 10, 20

должен вернуть 10 самых крутых игроков на 3 странице
 
 
Сообщения:1339
В Java 8 в Map.Entry есть компаратор, который может сортировать мапу по значению.

Comparator<Map.Entry<String, Double>> byValue = Map.Entry.comparingByValue();
result.entrySet().stream()
        .sorted(byValue.reversed())
        .forEach(System.out::println);

datatalks.ru - анализ данных, статистика, машинное обучение
 
 
Сообщения:33
loptop:
Добавьте в свой проект миниБД, тот же sqllite, тогда вы сможете вытаскивать пользователей и сортировать их одним запросом, например
SELECT * FROM User ORDER BY score desc LIMIT 10, 20

должен вернуть 10 самых крутых игроков на 3 странице

Я подумаю над этим, но не особо хочу добавлять БД...
stolzen:
В Java 8 в Map.Entry есть компаратор, который может сортировать мапу по значению.

Comparator<Map.Entry<String, Double>> byValue = Map.Entry.comparingByValue();
result.entrySet().stream()
        .sorted(byValue.reversed())
        .forEach(System.out::println);

Спасибо, возьму на заметку)
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет