Сортировка HashMap с сохранением дубликатов - PullRequest
2 голосов
/ 13 января 2012

Я пытаюсь отсортировать HashMap двумя способами. Способ по умолчанию: в алфавитном порядке по значению, второй способ: в числовом виде по ключу, причем верхнее число находится вверху. Я искал вокруг, но не могу найти ничего по этому вопросу, и то, что я нахожу, не работает. Если невозможно отсортировать их оба (я хочу, чтобы человек с наивысшей клавишей вверху уменьшался, поскольку у людей нижние клавиши, а затем сортировал по алфавиту все остальные (люди с 0 в качестве ключа).

Вот что я пробовал до сих пор:

private HashMap<String, Integer> userGains = new HashMap<String, Integer>();

public void sortGains(int skill, int user) {
    userGains.put(users.get(user).getUsername(), users.get(user).getGainedExperience(skill));
    HashMap<String, Integer> map = sortHashMap(userGains);
    for (int i = 0; i < map.size(); i++) {
        Application.getTrackerOutput().getOutputArea(skill).append(users.get(user).getUsername() + " gained " + map.get(users.get(user).getUsername()) + "  experience in " + getSkillName(skill) + ".\n");
    }
}

public LinkedHashMap<String, Integer> sortHashMap(HashMap<String, Integer> passedMap) {
    List<String> mapKeys = new ArrayList<String>(passedMap.keySet());
    List<Integer> mapValues = new ArrayList<Integer>(passedMap.values());
    LinkedHashMap<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();

    Collections.sort(mapValues);
    Collections.sort(mapKeys);

    Iterator<Integer> it$ = mapValues.iterator();
    while (it$.hasNext()) {
        Object val = it$.next();
        Iterator<String> keyIt = mapKeys.iterator();
        while (keyIt.hasNext()) {
            Object key = keyIt.next();
            String comp1 = passedMap.get(key).toString();
            String comp2 = val.toString();
            if (comp1.equals(comp2)) {
                passedMap.remove(key);
                mapKeys.remove(key);
                sortedMap.put((String) key, (Integer) val);
                break;
            }
        }
    }
    return sortedMap;
}

Так как вы не можете запустить это вот SSCCE:

private HashMap<String, Integer> userGains = new HashMap<String, Integer>();

private Object[][] testUsers = { { "Test user", 15 }, { "Test", 25 }, { "Hello", 11 }, { "I'm a user", 21 }, { "No you're not!", 14 }, { "Yes I am!", 45 }, { "Oh, okay.  Sorry about the confusion.", 0 }, { "It's quite alright.", 0 } };

public static void main(String[] arguments) {
    new Sorting().sortGains();
}

public void sortGains() {
    for (Object[] test : testUsers) {
        userGains.put((String) test[0], (Integer) test[1]);
    }
    HashMap<String, Integer> map = sortHashMap(userGains);
    for (int i = 0; i < map.size(); i++) {
        System.out.println(testUsers[i][0] + " gained " + map.get(testUsers[i][0]) + "  experience.");
    }
}

public LinkedHashMap<String, Integer> sortHashMap(HashMap<String, Integer> passedMap) {
    List<String> mapKeys = new ArrayList<String>(passedMap.keySet());
    List<Integer> mapValues = new ArrayList<Integer>(passedMap.values());
    LinkedHashMap<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();

    Collections.sort(mapValues);
    Collections.sort(mapKeys);

    Iterator<Integer> it$ = mapValues.iterator();
    while (it$.hasNext()) {
        Object val = it$.next();
        Iterator<String> keyIt = mapKeys.iterator();
        while (keyIt.hasNext()) {
            Object key = keyIt.next();
            String comp1 = passedMap.get(key).toString();
            String comp2 = val.toString();
            if (comp1.equals(comp2)) {
                passedMap.remove(key);
                mapKeys.remove(key);
                sortedMap.put((String) key, (Integer) val);
                break;
            }
        }
    }
    return sortedMap;
}

Вывод программы в данный момент:

Test user gained 15  experience.
Test gained 25  experience.
Hello gained 11  experience.
I'm a user gained 21  experience.
No you're not! gained 14  experience.
Yes I am! gained 45  experience.
Oh, okay.  Sorry about the confusion. gained 0  experience.
It's quite alright. gained 0  experience.

Когда мне нужно, чтобы это было:

Yes I am! gained 45  experience. // start numeric sorting here, by highest key.
Test gained 25  experience.
I'm a user gained 21  experience.
Test user gained 15  experience.
No you're not! gained 14  experience.
Hello gained 11  experience.
It's quite alright. gained 0  experience. // start alphabetical sorting here, if possible.
Oh, okay.  Sorry about the confusion. gained 0  experience.

Есть идеи?

Ответы [ 3 ]

5 голосов
/ 13 января 2012

Невозможно отсортировать HashMap на всех .По определению, ключи в HashMap неупорядочены.Если вы хотите, чтобы ключи вашего Map были упорядочены, используйте TreeMap с соответствующим объектом Comparator.Вы можете создать несколько TreeMaps с разными Comparator s, если хотите получить доступ к одним и тем же данным несколькими способами.

1 голос
/ 13 января 2012

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

По сути, вы создаете Comparator, у которого есть поле, которое указывает на TreeMap (чтобы он мог искать значения). И TreeMap использует этот компаратор. Когда элементы добавляются в TreeMap, Comparator просматривает значения и сравнивает

  • если значение a <значение b, вернуть 1 </li>
  • если значение a> значение b, вернуть -1
  • если ключ a <ключ b, вернуть 1 </li>
  • если клавиша a> клавиша b, вернуть -1
  • в противном случае вернуть 0

Копирование большого количества кода из этого ответа (без проверки, чтобы увидеть, работает ли код, так как это только для идеи):

public class Main {

    public static void main(String[] args) {

        ValueComparator<String> bvc =  new ValueComparator<String>();
        TreeMap<String,Integer> sorted_map = new TreeMap<String,Integer>(bvc);
        bvc.setBase(sorted_map);

        // add items
        // ....

        System.out.println("results");
            for (String key : sorted_map.keySet()) {
            System.out.println("key/value: " + key + "/"+sorted_map.get(key));
        }
     }

}

class ValueComparator implements Comparator<String> {
    Map base;

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

    public int compare(String a, String b) {
        Integer value_a = base.get(a);
        Integer value_b = base.get(b);

        if(value_a < value_b) {
            return 1;
        }
        if(value_a>< value_b) {
            return -1;
        }
        return a.compareTo(b);
    }
}
1 голос
/ 13 января 2012

Вы допустили ошибку при отображении значений.

HashMap<String, Integer> map = sortHashMap(userGains);
for (int i = 0; i < map.size(); i++) {
    System.out.println(testUsers[i][0] + " gained " + map.get(testUsers[i][0]) + "  experience.");
}

Вам необходимо отобразить значения карты вместо значений исходного массива.

Это должно сделать:

HashMap<String, Integer> map = sortHashMap(userGains);
for (Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " gained " + entry.getValue() + "  experience.");
}

Вам нужно только отменить заказ.Далее я рекомендую объявить против Map вместо HashMap или LinkedHashMap, чтобы избежать путаницы между вами и другими.Кроме того, ваша сортировка может быть проще с Comparable.Вот улучшение:

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

private Object[][] testUsers = { { "Test user", 15 }, { "Test", 25 }, { "Hello", 11 }, { "I'm a user", 21 }, { "No you're not!", 14 }, { "Yes I am!", 45 }, { "Oh, okay.  Sorry about the confusion.", 0 }, { "It's quite alright.", 0 } };

public static void main(String[] arguments) {
    new Sorting().sortGains();
}

public void sortGains() {
    for (Object[] test : testUsers) {
        userGains.put((String) test[0], (Integer) test[1]);
    }

    Map<String, Integer> map = createSortedMap(userGains);

    for (Entry<String, Integer> entry : map.entrySet()) {
        System.out.println(entry.getKey() + " gained " + entry.getValue() + "  experience.");
    }
}

public Map<String, Integer> createSortedMap(Map<String, Integer> passedMap) {
    List<Entry<String, Integer>> entryList = new ArrayList<Entry<String, Integer>>(passedMap.entrySet());

    Collections.sort(entryList, new Comparator<Entry<String, Integer>>() {

        @Override
        public int compare(Entry<String, Integer> e1, Entry<String, Integer> e2) {
            if (!e1.getValue().equals(e2.getValue())) {
                return e1.getValue().compareTo(e2.getValue()) * -1; // The * -1 reverses the order.
            } else {
                return e1.getKey().compareTo(e2.getKey());
            }
        }
    });

    Map<String, Integer> orderedMap = new LinkedHashMap<String, Integer>();

    for (Entry<String, Integer> entry : entryList) {
        orderedMap.put(entry.getKey(), entry.getValue());
    }

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