反向哈希图
Reverse HashMap
我有一个 HashMap
看起来像 :
HashMap<Player, Integer> playerHashMap = new HashMap<>();
Player 是包含姓名、号码、年龄等的对象
现在我已经对它进行了排序,它看起来像这样:
key , value
-----------------
Player1, 1
Player2, 2
Player3, 4
Player4, 6
但是我想实现按值反转这张图,像这样:
key , value
-----------------
Player4, 6
Player3, 4
Player2, 2
Player1, 1
有什么想法吗?
排序方法(按值排序)如下所示:
private static HashMap<Player, Integer> sortByValues(HashMap<Player, Integer> map) {
List list = new LinkedList(map.entrySet());
Collections.sort(list, new Comparator<Object>() {
public int compare(Object o1, Object o2) {
return ((Comparable) ((Map.Entry) (o1)).getValue())
.compareTo(((Map.Entry) (o2)).getValue());
}
});
HashMap<Player, Integer> sortedHashMap = new LinkedHashMap<Player, Integer>();
for (Iterator<?> it = list.iterator(); it.hasNext();) {
Map.Entry<Player, Integer> entry = (Map.Entry<Player, Integer>) it.next();
sortedHashMap.put(entry.getKey(), entry.getValue());
}
return sortedHashMap;
}
事实是 HashMap 不保证任何特定的迭代顺序。所以你只是 'got lucky' 你的列表以任何方式排序。要解决您的问题,您必须将 table 行作为一个实体进行排序,以便 value
链接到相应的 player
。为此,您实际上可以直接使用 Map.Entry,并将它们放入集合中,但您需要一个自定义比较器。在您的示例中,最好使用通常的 ArrayList
来完成任务,并使用 Collections.sort()
对其进行排序。要颠倒顺序,请从比较器中否定您 return 的结果:
class Player {}
public static void main(String[] args) {
HashMap<Player, Integer> all = new HashMap<>();
List<Map.Entry<Player, Integer>> sorted = sortByValues(all);
for (Map.Entry<Player, Integer> e : sorted) {
System.out.println("Player: " + e.getKey());
System.out.println("Value: " + e.getValue());
}
}
private static List<Map.Entry<Player, Integer>> sortByValues(HashMap<Player, Integer> map) {
List<Map.Entry<Player, Integer>> list = new ArrayList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Player, Integer>>() {
public int compare(Map.Entry<Player, Integer> e1, Map.Entry<Player, Integer> e2) {
//use minus to reverse the order
return -e1.getValue().compareTo(e2.getValue());
}
});
return list;
}
你是怎么排序的?
(基本)HashMap 不定义元素之间的顺序。
我用这个:
public static <K extends Comparable<K>,V> List<Entry<K,V>> sortByKeys(Map<K,V> map, final Comparator<K> cmp)
{
List<Entry<K, V>> ret = new ArrayList<>();
for(Entry<K,V> kv : map.entrySet())
ret.add(kv);
Collections.sort(ret,((Comparator) new Comparator<Entry<K,?>>()
{
@Override
public int compare(Entry<K, ?> o1, Entry<K, ?> o2)
{
return cmp.compare(o1.getKey(), o2.getKey());
}
}));
return ret;
}
您可以指定您的比较器来对返回的挂单列表进行排序。
=====
编辑:
使用关心顺序的 Map 实现是个好主意。
您可以简单地修改您的代码以指定排序,只需修改 header 和这一行:
-private static HashMap<Player, Integer> sortByValues(HashMap<Player, Integer> map) {
+private static HashMap<Player, Integer> sortByValues(HashMap<Player, Integer> map, final boolean reverse) {
并在块中:
-return ((Comparable) ((Map.Entry) (o1)).getValue())
+return (reverse?-1:1)*((Comparable) ((Map.Entry) (o1)).getValue())
您可以使用 java.util.TreeMap 并传递比较器以按照您想要的方式对它们进行排序。
但是我仍然想知道为什么您将 Player 作为 Key 而将 Integer 作为 Value ?
如果您仅使用 Integer 进行排序,那么您可能希望交换 Key 和 value 以更好地使用 Maps 的标准方式。
此外,如果您不需要使用哈希技术访问对象(也就是说,如果您的集合不会很大,哈希会提高性能)考虑一个简单的列表。
我不确定您为什么要 return 单独映射。您已经有了 List,您可以简单地按存储条目的值进行排序。
也不要限制自己使用特定类型的映射,例如 HashMap。您可能一无所获,但很难将您的实现更改为其他类型的 Map。
因此您的代码可能如下所示:
private static List<Map.Entry<Player, Integer>> entriesSoltedByValue(
Map<Player, Integer> map) {
List<Map.Entry<Player, Integer>> list = new ArrayList<>(map.entrySet());
list.sort(Comparator.comparing(Map.Entry<Player, Integer>::getValue).reversed());
return list;
}
或使用流:
private static List<Map.Entry<Player, Integer>> entriesSoltedByValue(
Map<Player, Integer> map) {
return map.entrySet()
.stream()
.sorted(Comparator
.comparing(Map.Entry<Player, Integer>::getValue)
.reversed())
.collect(Collectors.toList());
}
简而言之,您不能将订单设置为 HashMap
。如果您想要与 HashMap
相同的功能但有顺序,您应该使用 TreeMap.
Map<String, Integer> orderedMap = new TreeMap(Collections.reverseOrder());
orderedMap.putAll(playerHashMap);
HashMap
给你 O(1) 插入和搜索,而它们在 TreeMap
中是 O(log(n)) 因为它是在内部用红黑树实现的。
我有一个 HashMap
看起来像 :
HashMap<Player, Integer> playerHashMap = new HashMap<>();
Player 是包含姓名、号码、年龄等的对象
现在我已经对它进行了排序,它看起来像这样:
key , value
-----------------
Player1, 1
Player2, 2
Player3, 4
Player4, 6
但是我想实现按值反转这张图,像这样:
key , value
-----------------
Player4, 6
Player3, 4
Player2, 2
Player1, 1
有什么想法吗?
排序方法(按值排序)如下所示:
private static HashMap<Player, Integer> sortByValues(HashMap<Player, Integer> map) {
List list = new LinkedList(map.entrySet());
Collections.sort(list, new Comparator<Object>() {
public int compare(Object o1, Object o2) {
return ((Comparable) ((Map.Entry) (o1)).getValue())
.compareTo(((Map.Entry) (o2)).getValue());
}
});
HashMap<Player, Integer> sortedHashMap = new LinkedHashMap<Player, Integer>();
for (Iterator<?> it = list.iterator(); it.hasNext();) {
Map.Entry<Player, Integer> entry = (Map.Entry<Player, Integer>) it.next();
sortedHashMap.put(entry.getKey(), entry.getValue());
}
return sortedHashMap;
}
事实是 HashMap 不保证任何特定的迭代顺序。所以你只是 'got lucky' 你的列表以任何方式排序。要解决您的问题,您必须将 table 行作为一个实体进行排序,以便 value
链接到相应的 player
。为此,您实际上可以直接使用 Map.Entry,并将它们放入集合中,但您需要一个自定义比较器。在您的示例中,最好使用通常的 ArrayList
来完成任务,并使用 Collections.sort()
对其进行排序。要颠倒顺序,请从比较器中否定您 return 的结果:
class Player {}
public static void main(String[] args) {
HashMap<Player, Integer> all = new HashMap<>();
List<Map.Entry<Player, Integer>> sorted = sortByValues(all);
for (Map.Entry<Player, Integer> e : sorted) {
System.out.println("Player: " + e.getKey());
System.out.println("Value: " + e.getValue());
}
}
private static List<Map.Entry<Player, Integer>> sortByValues(HashMap<Player, Integer> map) {
List<Map.Entry<Player, Integer>> list = new ArrayList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Player, Integer>>() {
public int compare(Map.Entry<Player, Integer> e1, Map.Entry<Player, Integer> e2) {
//use minus to reverse the order
return -e1.getValue().compareTo(e2.getValue());
}
});
return list;
}
你是怎么排序的? (基本)HashMap 不定义元素之间的顺序。 我用这个:
public static <K extends Comparable<K>,V> List<Entry<K,V>> sortByKeys(Map<K,V> map, final Comparator<K> cmp)
{
List<Entry<K, V>> ret = new ArrayList<>();
for(Entry<K,V> kv : map.entrySet())
ret.add(kv);
Collections.sort(ret,((Comparator) new Comparator<Entry<K,?>>()
{
@Override
public int compare(Entry<K, ?> o1, Entry<K, ?> o2)
{
return cmp.compare(o1.getKey(), o2.getKey());
}
}));
return ret;
}
您可以指定您的比较器来对返回的挂单列表进行排序。
=====
编辑: 使用关心顺序的 Map 实现是个好主意。 您可以简单地修改您的代码以指定排序,只需修改 header 和这一行:
-private static HashMap<Player, Integer> sortByValues(HashMap<Player, Integer> map) {
+private static HashMap<Player, Integer> sortByValues(HashMap<Player, Integer> map, final boolean reverse) {
并在块中:
-return ((Comparable) ((Map.Entry) (o1)).getValue())
+return (reverse?-1:1)*((Comparable) ((Map.Entry) (o1)).getValue())
您可以使用 java.util.TreeMap 并传递比较器以按照您想要的方式对它们进行排序。
但是我仍然想知道为什么您将 Player 作为 Key 而将 Integer 作为 Value ? 如果您仅使用 Integer 进行排序,那么您可能希望交换 Key 和 value 以更好地使用 Maps 的标准方式。 此外,如果您不需要使用哈希技术访问对象(也就是说,如果您的集合不会很大,哈希会提高性能)考虑一个简单的列表。
我不确定您为什么要 return 单独映射。您已经有了 List,您可以简单地按存储条目的值进行排序。
也不要限制自己使用特定类型的映射,例如 HashMap。您可能一无所获,但很难将您的实现更改为其他类型的 Map。
因此您的代码可能如下所示:
private static List<Map.Entry<Player, Integer>> entriesSoltedByValue(
Map<Player, Integer> map) {
List<Map.Entry<Player, Integer>> list = new ArrayList<>(map.entrySet());
list.sort(Comparator.comparing(Map.Entry<Player, Integer>::getValue).reversed());
return list;
}
或使用流:
private static List<Map.Entry<Player, Integer>> entriesSoltedByValue(
Map<Player, Integer> map) {
return map.entrySet()
.stream()
.sorted(Comparator
.comparing(Map.Entry<Player, Integer>::getValue)
.reversed())
.collect(Collectors.toList());
}
简而言之,您不能将订单设置为 HashMap
。如果您想要与 HashMap
相同的功能但有顺序,您应该使用 TreeMap.
Map<String, Integer> orderedMap = new TreeMap(Collections.reverseOrder());
orderedMap.putAll(playerHashMap);
HashMap
给你 O(1) 插入和搜索,而它们在 TreeMap
中是 O(log(n)) 因为它是在内部用红黑树实现的。