最近在刷題的過程中,在使用HashMap進行文件排序遇到的小問題。
題目:
開發一個簡單錯誤記錄功能小模塊,能夠記錄出錯的代碼所在的文件名稱和行號。
處理:
1.記錄最多8條錯誤記錄,對相同的錯誤記錄(即文件名稱和行號完全匹配)只記錄一條,錯誤計數增加;(文件所在的目錄不同,文件名和行號相同也要合併)
2.超過16個字符的文件名稱,只記錄文件的最後有效16個字符;(如果文件名不同,而只是文件名的後16個字符和行號相同,也不要合併)
3.輸入的文件可能帶路徑,記錄文件名稱不能帶路徑
輸入描述:
一行或多行字符串。每行包括帶路徑文件名稱,行號,以空格隔開。
文件路徑爲windows格式
如:E:\V1R2\product\fpgadrive.c 1325
輸出描述:
將所有的記錄統計並將結果輸出,格式:文件名代碼行數數目,一個空格隔開,如: fpgadrive.c 1325 1
結果根據數目從多到少排序,數目相同的情況下,按照輸入第一次出現順序排序。
如果超過8條記錄,則只輸出前8條記錄.
如果文件名的長度超過16個字符,則只輸出後16個字符
輸入例子1:
E:\V1R2\product\fpgadrive.c 1325
輸出例子1:
fpgadrive.c 1325 1
自己的代碼:
在使用HashMap的時候,提交不通過,而使用LinkedHashMap的時候卻提交通過。
public static void main(String []args) {
Scanner sr = new Scanner(System.in);
HashMap<String, Integer> map = new HashMap<>(); //LinkedHashMap
do {
String str = sr.next();
int index = sr.nextInt();
int in = str.lastIndexOf('\\');
str = str.substring(in+1, str.length()) + " " + index;
if (map.containsKey(str)) {
map.put(str, map.get(str) + 1);
} else {
map.put(str, 1);
}
} while (sr.hasNext());
sr.close();
//對記錄排序
//對記錄進行排序
List<Map.Entry<String, Integer>> list = new LinkedList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
//降序
@Override
public int compare(Entry<String, Integer> arg0, Entry<String, Integer> arg1) {
return (arg1.getValue() - arg0.getValue()) == 0 ? (arg0.getValue() - arg1.getValue()) : (arg1.getValue() - arg0.getValue());
}
});
//只輸出前8條
int m = 0;
for (Map.Entry<String, Integer> mapping : list) {
m++;
if (m <= 8) {
String[] str = mapping.getKey().split(" ");
String k = str[0].length() > 16 ? str[0].substring(str[0].length() - 16) : str[0];
String n = str[1];
System.out.println(k + " " + n + " " + mapping.getValue());
} else {
break;
}
}
}
HashMap輸出結果:
總結分析:LinkedHashmap 的特點是put進去的對象位置未發生變化,而HashMap會發生變化.
java爲數據結構中的映射定義了一個接口java.util.Map;它有四個實現類,分別是HashMap Hashtable LinkedHashMap 和TreeMap.
Map主要用於存儲健值對,根據鍵得到值,因此不允許鍵重複(重複了覆蓋了),但允許值重複。
Hashmap 是一個最常用的Map,它根據鍵的HashCode值存儲數據(重複存儲入相同的hashCode不會導致錯誤發生,但只會保留一個值,equlas和hashCode的規則,hashCode不同的可能equals。但是不equals一定hashCode不同),根據鍵可以直接獲取它的值,具有很快的訪問速度,遍歷時,取得數據的順序是完全隨機的。
HashMap最多隻允許一條記錄的鍵爲Null;允許多條記錄的值爲 Null;
HashMap默認按照key的升序排列存儲的數據,因此會在一定程度上影響到性能。
HashMap不支持線程的同步,即任一時刻可以有多個線程同時寫HashMap;可能會導致數據的不一致。
如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap;但是這樣的話性能會有影響。
Hashtable與 HashMap類似,它繼承自Dictionary類,不同的是:它不允許記錄的鍵或者值爲空;它支持線程的同步,即任一時刻只有一個線程能寫Hashtable,因此也導致了 Hashtable在寫入時會比較慢。
LinkedHashMap 是HashMap的一個子類,保存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時,先得到的記錄肯定是先插入的(先進先出,類似棧).也可以在構造時用帶參數,按照應用次數排序。在遍歷的時候會比HashMap慢(因爲linkedhashmap需要保存插入的順序屬於需要額外開銷),不過有種情況例外,當HashMap容量很大,實際數據較少時,遍歷起來可能會比LinkedHashMap慢,因爲LinkedHashMap的遍歷速度只和實際數據有關,和容量無關,而HashMap的遍歷速度和他的容量有關。
TreeMap實現SortMap接口,能夠把它保存的記錄根據鍵排序,默認是按鍵值的升序排序,也可以指定排序的比較器,當用Iterator 遍歷TreeMap時,得到的記錄是排過序的。
一般情況下,我們用的最多的是HashMap,在Map 中插入、刪除和定位元素,HashMap 是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那麼TreeMap會更好。如果需要輸出的順序和輸入的相同,那麼用LinkedHashMap可以實現,它還可以按讀取順序來排列.