2012-01-13 4 views
2

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

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

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. 

Любое понимание?

ответ

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."); 
} 

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

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

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; 
} 
+0

Удивительный! Это наоборот, знаете ли вы, как я могу отменить то, что выводит метод? Изменить: изменение 'Collections.sort (mapValues);' to 'Collections.sort (mapValues, Collections.reverseOrder());' работал просто отлично :) Еще раз спасибо. – Aeterna

+0

Я обновил ответ на примере. – BalusC

+0

Спасибо, это намного легче понять, чем тот, который я использую! – Aeterna

5

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

+0

Есть ли способ, которым я мог бы отсортировать полученный опыт пользователя? У меня есть ** Пользователь ** суперкласс, который содержит всю информацию в нем, а затем ArrayList пользователей, которая содержит их все. – Aeterna

+0

Конечно, вы можете определенно отсортировать 'ArrayList'; используйте 'Collections.sort()' и предоставите подходящую реализацию 'Comparator'. –

+0

А я вижу. Я смотрел ранее и нашел предоставленный метод для сортировки 'HashMap', но я думаю, что это было слишком хорошо, чтобы быть правдой. Использует ли 'Collections.sort()' разрешить мне сохранять дубликаты, или это делается в «Компараторе»? – Aeterna

1

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

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

  • , если значение а < значения б, вернуть 1
  • если значение а> значение Ь, возвращает -1
  • если ключ на < ключ б, вернуть 1
  • если ключ а> ключ б, вернуть -1
  • в противном случае, возврат 0

Copy (без проверки того, работает ли код, поскольку это просто идея):

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); 
    } 
} 
Смежные вопросы