[英]Sorting of Map based on keys
這基本上不是基於鍵對HashMap
進行排序的方法。 為此我可以直接使用TreeMap
而不用眨眼:)
我現在擁有的是
Map<String, Object> favoritesMap = new HashMap<String, Object>();
and its contents can be
["Wednesdays" : "abcd"]
["Mondays" : "1234"]
["Not Categorized" : "pqrs"]
["Tuesdays" : "5678"]
我想基於鍵對HashMap進行排序,除此之外,我需要“未分類”才能找到最后一個。
因此,在迭代keySet時所期望的是
["Mondays", "Tuesdays", "Wednesdays", "Not Categorized"] i.e. sorted on keys and "Not Categorized" is the last one
考慮在創建時加入HashMap
並在最后添加["Not Categorized" : "pqrs"]
但HashMap
不保證順序:)
解決方案的任何其他指針?
出於某些外部原因,您是否明確排除了TreeMap
? 如果不是,你顯然可以將TreeMap
與特制的Comparator
。
您是否考慮過其他任何SortedMap
?
如果TreeMap
肯定是出局的話,我會擴展HashMap
並讓它看起來總是有一個條目,但這肯定不是一件小事。 在走這條路之前,你應該有一個很好的理由不使用SortedMap
。
添加
下面是一個示例,說明如何使用TreeMap
使特定條目始終排序到最后:
// This key should always appear at the end of the list.
public static final String AtEnd = "Always at the end";
// A sample map.
SortedMap<String, String> myMap =
new TreeMap<>(
new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.equals(AtEnd) ? 1 : o2.equals(AtEnd) ? -1 : o1.compareTo(o2);
}
});
private void test() {
myMap.put("Monday", "abc");
myMap.put("Tuesday", "def");
myMap.put("Wednesday", "ghi");
myMap.put(AtEnd, "XYZ");
System.out.println("myMap: "+myMap);
// {Monday=abc, Tuesday=def, Wednesday=ghi, Always at the end=XYZ}
}
我想知道你是否正在尋找一些變體?
您可以使用LinkedHashMap
來實現此目的,因為它保證按插入順序返回結果。
另請查看以下帖子以了解地圖類型之間的區別。
或者只是創建一個自定義類,其中包含與值不同的鍵。 根據該類的鍵進行排序。 對於您的情況,使密鑰與日期相同,對於“未分類”的情況,確保其密鑰的啟動時間晚於任何其他密鑰,例如使其“Z_Not Categorized”。
public ComplexKey
{
String key;
String value;
}
ComplexKey monday = new ComplexKey("monday", "monday");
ComplexKey notCategorized = new ComplexKey("Z_Not Categorized", "Not Categorized");
然后你可以編寫一個自定義比較器,根據complexKey
類的鍵對值進行排序。
在你的情況下,我會使用TreeMap:
Map<DayOfWeek, Object> favoritesMap = new TreeMap<>();
其中DayOfWeek
是一個你聲明的類:
class DayOfWeek implements Comparable<DayOfWeek> {
因為把日子作為字符串排序是不方便的。
事實上,鍵總是排序。 如果您多次輸出地圖,您會發現結果保持不變。
原因是散列。 每個對象都有hashCode()
方法。 哈希空間就像一個大型數組,它包含所有可能的哈希值作為索引。 當將新元素插入HashSet
或將新對放入HashMap
,根據其哈希碼將其放置在哈希空間中。 如果兩個元素具有相同的哈希碼,則將它們與equals()
方法進行比較,如果不相等,則將新元素放在它旁邊。
import java.util.*;
class MyString {
private String str;
public MyString (String str) {
this.str = str;
}
public String toString () {
return str;
}
public boolean equals (Object obj) {
if (obj.getClass().equals(MyString.class)) {
return obj.toString().equals(str);
}
return false;
}
public int hashCode () {
if (str.equalsIgnoreCase("Not Categorized")) {
return Integer.MAX_VALUE;
} else if (str.hashCode() == Integer.MAX_VALUE) {
return 0;
}
return str.hashCode();
}
}
public class Test {
public static void main (String args[]) {
Map<MyString, String> m = new HashMap<MyString, String>();
m.put(new MyString("a"), "a");
m.put(new MyString("c"), "c");
m.put(new MyString("Not Categorized"), "NC");
m.put(new MyString("b"), "b");
Set<MyString> keys = m.keySet();
for (MyString k : keys) {
System.out.println(m.get(k));
}
}
}
結果是“未分類”總是最后出現。 原因很簡單:它的哈希值始終是整數的最大值。
我創建一個String包裝類的原因是String類是final,它不能被擴展。 因此,通過這種方式,您的類結構會有一些變化,但不會太多。
public static void main (String args[]) {
Map<String, String> m = new TreeMap<String, String>(new Comparator<String>() {
public int compare (String s1, String s2) {
if (s1.equals(s2)) {
return 0;
}
if (s1.equalsIgnoreCase("Not Categorized")) {
return 1;
}
if (s2.equalsIgnoreCase("Not Categorized")) {
return -1;
}
if (s1.hashCode() > s2.hashCode()) {
return 1;
} else if (s1.hashCode() < s2.hashCode()) {
return -1
} else {
return 0;
}
}
public boolean equals (Object obj) {
return false;
}
});
m.put("a", "a");
m.put("c", "c");
m.put("Not Categorized", "NC");
m.put("b", "b");
Set<String> keys = m.keySet();
for (String k : keys) {
System.out.println(m.get(k));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.