2014-09-27 2 views
0

У меня есть карта, как такПолучить Top 5 значений Из Карта

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

Это будет заполняться с большим количеством entrys и то, что я пытаюсь сделать, это своего рода Top 5 статистики.

То, что я прямо сейчас

int maxValueInMap=(Collections.max(map.values())); 
for (Entry<String, Integer> entry : map.entrySet()) {      
if (entry.getValue()==maxValueInMap) { 
    name = entry.getKey(); 
} 
} 

Который работает отлично подходит для получения ключа/значение числа 1 верхнего наибольшего значения в карте, но я не могу понять, как я могу получить топ 5 наивысший и иметь что-то вроде

int maxValueInMap=(Collections.max(map.values())); 
for (Entry<String, Integer> entry : map.entrySet()) {      
if (entry.getValue()==maxValueInMap) { 
    name = entry.getKey(); 
    name2 = entry.getKey(2ndHighest); 
    //so on 
} 
} 

Поблагодарили бы за любую помощь, спасибо.

EDIT

Я нашел этот код, который работает, как он хочет, чтобы это сделать

public class Main { 

public static void main(String[] args) { 

    HashMap<String,Integer> map = new HashMap<String,Integer>(); 
    ValueComparator bvc = new ValueComparator(map); 
    TreeMap<String,Integer> sorted_map = new TreeMap<String,Integer>(bvc); 

    map.put("a",10); 
    map.put("b",6); 
    map.put("c",6); 
    map.put("d",56); 
    map.put("e",54); 
    map.put("f",32); 
    map.put("g",1); 

    System.out.println("unsorted map: "+map); 
    sorted_map.putAll(map); 
    System.out.println("results: "+sorted_map); 
} 
} 

class ValueComparator implements Comparator<String> { 

Map<String, Integer> base; 
public ValueComparator(Map<String, Integer> base) { 
    this.base = base; 
} 

public int compare(String a, String b) { 
    if (base.get(a) >= base.get(b)) { 
     return -1; 
    } else { 
     return 1; 
    } 
} 
} 

, которая печатает

unsorted map: {a=10, b=6, c=6, d=56, e=54, f=32, g=1} 
results: {d=56, e=54, f=32, a=10, c=6, b=6, g=1} 

Но как бы я получить только лучшие 5 из sorted_map а не все записи?

+0

Вы хотите получить только лучшие оценки или также связанные ключи? – Dici

+0

Да, ключи от меня, мне нужно знать, с каким игроком связан верхний балл – user3439600

+0

@ user3439600 - Извините, но я счел необходимым предупредить будущих читателей о том, что найденное вами решение неверно. (Сравните с тем, что я сказал, отвечая, чтобы понять, почему ...). Без предупреждения люди могут слепо копировать и вставлять их в свой собственный код и сжигаться. Можно сказать со значительным обоснованием, что он «служит им правильным» ...но даже в этом случае мы не хотели бы косвенно отвечать. –

ответ

2

Вы хотите отсортировать товары по значению, это не может быть сделано по умолчанию в HashMap или TreeMap.

Вы должны рассмотреть свой собственный класс и использовать TreeSet:

class Entry implements Comparable<? extends Entry> { 
    public final String name; 
    public final Integer value; 

    .. 

    public int compareTo(Entry o) { return value == o.value ? o.name.compareTo(name) : o.value - value; } 

    public boolean equals(Object o) { 
    // equals consistent to compareTo (name and value equal for both entries) 
    } 
} 

SortedSet<Entry> set = new TreeSet<Entry>(); 
set.add(...) 
+0

'value' должно быть типа' Integer'. – Dici

+0

Как мне получить ключи/значения из моей исходной карты? – user3439600

+1

Я не думаю, что это работает. См. Мой ответ за подсказки о том, почему. Для начала, это 'compareTo' приведет к устранению« дубликатов ». –

2

Простой способ сделать это это:

  • Копировать запись набор из HashMap в массив
  • Сортировка массива
  • Возьмите первые 5 записей.

Однако шаг сортировка O(N log N), и это убийца производительности, если N велико, и вам нужно, чтобы получить лучшие 5 раз ... и целые значения (например, отсчитывает) могут быть обновлены.


Если вам нужна более высокая производительность, что нужно более сложные структуры данных, которые позволяют инкрементного обновления (чтобы избежать повторной сортировки):

  • A 1 к 1 отображению строк в строку/кол-пар
  • Упорядоченная коллекция строк/кол пар, которые упорядочиваются подсчетов

Если вы ограничиваете себя в ст andard, это можно сделать, используя следующее:

  • Пользовательский Pair класс для хранения пар.
  • A HashMap<String, Pair> для прямого отображения.
  • A TreeSet<Pair> для хранения пар в порядке.
  • A (стабильный) компаратор, который заказывает пары, в первую очередь, счетным счетом Pair. (Последнее важно. Компаратор не должен обрабатывать объекты Pair с одинаковым подсчетом равным, или Pair объекты будут ошибочно удалены как дубликаты!).

Последнее, что вы помните, что TreeSet не будет автоматически обновляться должным образом, если вы просто изменить count в Pair. Вместо этого вам нужно:

  1. Удалите Pair из Центра обновления на TreeSet
  2. count
  3. Добавьте Pair обратно в TreeSet.

Остальное «просто программирование». (Но слишком сложно для меня, чтобы писать, компилировать, тестировать и т.д. прямо сейчас :-))


Если вы выше правильно, а затем добавить или приращением граф должен быть O(log N) и найти первые 5 записей должны be O(1). Однако, поскольку вы используете это решение для замены O(1) add/increment, это только четкий выигрыш в производительности, если N большой (достаточно), а «верхний 5» - относительно обычная операция.

Также стоит отметить, что вы также можете получить верхние M элементов в несортированной коллекции N элементов в O(N log M). Если M - небольшая константа, которая сводится к O(N). Другими словами, он масштабируется лучше, чем сортировка записи, установленной в простой версии вверху. (И это может быть быстрее для малых N тоже.)


В ответ на этот последующий вопрос:

Но как бы я получить только лучшие 5 из sorted_map, а не все entrys ??

Создайте итератор и просто позвоните next() 5 раз!

Но следует также отметить, что код, который вы нашли, это INCORRECT. Я настоятельно рекомендую вам сделать это для себя и тщательно протестировать его. (Или ограничьте свой поиск доступными библиотеками, которые включают в себя достойный комплект тестов модулей.)

+0

Но как я могу сохранить связанные ключи, если я использую список для значений? – user3439600

+0

@ user3439600 - Прочтите обновление. (Ответ: вы не должны этого делать. Поддержание простого списка, упорядоченного по 'count', даст вам« O (N) »производительность при вставке/обновлении.) –

+0

@StephenC: вы действительно имели в виду' HashMap 'а не' HashMap '? – Dici

Смежные вопросы