[英]Comparing integer values of 2 or more keys of one hashmap to 2 values in another hashmap
[英]Comparing keys in HashMap and Values
我有一個HashMap如下-
HashMap<String, Integer> BC = new HashMap<String, Integer>();
它存儲為鍵-“令牌/年齡”和值-“每個令牌/標簽的頻率”。
例-
"the/at" 153
"that/cs" 45
"Ann/np" 3
現在,我解析每個鍵,並檢查同一令牌是否說“ the”是否與多個標簽相關聯,然后取兩個標簽中最大的一個。
例-
"the/at" 153
"the/det" 80
然后,我將鍵"the/at"
的值153
。
我編寫的代碼如下:
private HashMap<String, Integer> Unigram_Tagger = new HashMap<String, Integer>();
for(String curr_key: BC.keySet())
{
for(String next_key: BC.keySet())
{
if(curr_key.equals(next_key))
continue;
else
{
String[] split_key_curr_key = curr_key.split("/");
String[] split_key_next_key = next_key.split("/");
//out.println("CK- " + curr_key + ", NK- " + next_key);
if(split_key_curr_key[0].equals(split_key_next_key[0]))
{
int ck_v = 0, nk_v = 0;
ck_v = BC.get(curr_key);
nk_v = BC.get(next_key);
if(ck_v > nk_v)
Unigram_Tagger.put(curr_key, BC.get(curr_key));
else
Unigram_Tagger.put(next_key, BC.get(next_key));
}
}
}
}
但是此代碼的計算時間太長,因為原始的HashMap'BC'具有68442個條目,大約等於其平方= 4684307364倍(加上更多)。
我的問題是-我可以使用更有效的方法完成相同的輸出嗎?
謝謝!
創建一個新的
Map<String,Integer> highCount = new HashMap<>();
會將令牌映射到最大數量。
一次通過按鍵。
將每個密鑰分成其組件令牌。
對於每個令牌,請查看highMap
。 如果密鑰不存在,請添加其數量。 如果條目已經存在並且當前計數大於先前的最大值,請替換映射中的最大值。
完成單遍操作后, highCount
將包含所有唯一令牌以及每個令牌看到的最高計數。
注意:此答案旨在為您提供一個起點,以開發一個完整的解決方案。 關鍵概念是創建並填充從令牌到某種“值”類型(不一定只是Integer
)的新映射,該映射可為您提供所需的功能。 值類型很可能是一個新的自定義類,用於存儲標記和計數。
當前方法最慢的部分是由於密鑰的成對比較。 首先,定義一個Tuple
類:
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
}
因此,您可以嘗試執行以下操作的算法:
HashMap<String, Tuple<String, Integer>> result
(key, value)
,其中key = "a/b"
,請檢查result.keySet().contains(a)
和result.keySet().contains(b)
。 a
和b
都不同時存在,則result.put(a, new Tuple<String, Integer>(b, value)
和result.put(b, new Tuple<String, Integer>(a, value))
a
存在時,比較value
和v = result.get(a)
。 如果value > v
,則從result
刪除a
和b
並執行步驟3。對b
進行相同操作。 否則,獲取下一個鍵值對。 遍歷舊的哈希映射並插入所有內容之后,可以通過轉換result
的鍵值輕松地重建所需的輸出。
關於算法的基本思想:
您應該獲取HashMap的entrySet()並將其轉換為List:
ArrayList<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
現在,您應該按字母順序對列表進行排序。 我們這樣做是因為HashMap沒有順序,因此您可以期望相應的鍵可能相距很遠。 但是通過對它們進行排序,所有相關的鍵都直接相鄰。
Collections.sort(list, Comparator.comparing(e -> e.getKey()));
由於按字母順序排序,條目“ the / at”和“ the / det”將彼此相鄰。
現在,您可以在記住最佳項目的同時遍歷整個列表,直到找到一個更好的項目,或者找到前綴不相同的第一個項目(例如“ the”)。
ArrayList<Map.Entry<String, Integer>> bestList = new ArrayList<>(); // The first entry of the list is considered the currently best item for it's group Map.Entry<String, Integer> currentBest = best.get(0); String key = currentBest.getKey(); String currentPrefix = key.substring(0, key.indexOf('/')); for (int i=1; i<list.size(); i++) { // The item we compare the current best with Map.Entry<String, Integer> next = list.get(i); String nkey = next.getKey(); String nextPrefix = nkey.substring(0, nkey.indexOf('/')); // If both items have the same prefix, then we want to keep the best one // as the current best item if (currentPrefix.equals(nextPrefix)) { if (currentBest.getValue() < next.getValue()) { currentBest = next; } // If the prefix is different we add the current best to the best list and // consider the current item the best one for the next group } else { bestList.add(currentBest); currentBest = next; currentPrefix = nextPrefix; } } // The last one must be added here, or we would forget it bestList.add(currentBest);
現在,您應該具有一個代表所需條目的Map.Entry對象列表。 復雜度應為n(log n),並受排序算法限制,而分組/收集項的復雜度為n。
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class Point {
public static void main(String[] args) {
HashMap<String, Integer> BC = new HashMap<>();
//some random values
BC.put("the/at",5);
BC.put("Ann/npe",6);
BC.put("the/atx",7);
BC.put("that/cs",8);
BC.put("the/aty",9);
BC.put("Ann/np",1);
BC.put("Ann/npq",2);
BC.put("the/atz",3);
BC.put("Ann/npz",4);
BC.put("the/atq",0);
BC.put("the/atw",12);
BC.put("that/cs",14);
BC.put("that/cs1",16);
BC.put("the/at1",18);
BC.put("the/at2",100);
BC.put("the/at3",123);
BC.put("that/det",153);
BC.put("xyx",123);
BC.put("xyx/w",2);
System.out.println("\nUnsorted Map......");
printMap(BC);
System.out.println("\nSorted Map......By Key");
//sort original map using TreeMap, it will sort the Map by keys automatically.
Map<String, Integer> sortedBC = new TreeMap<>(BC);
printMap(sortedBC);
// find all distinct prefixes by spliting the keys at "/"
List<String> uniquePrefixes = sortedBC.keySet().stream().map(i->i.split("/")[0]).distinct().collect(Collectors.toList());
System.out.println("\nuniquePrefixes: "+uniquePrefixes);
TreeMap<String,Integer> mapOfMaxValues = new TreeMap<>();
// for each prefix from the list above filter the entries from the sorted map
// having keys starting with this prefix
//and sort them by value in descending order and get the first which will have the highst value
uniquePrefixes.stream().forEach(i->{
Entry <String,Integer> e =
sortedBC.entrySet().stream().filter(j->j.getKey().startsWith(i))
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).findFirst().get();
mapOfMaxValues.put(e.getKey(), e.getValue());
});
System.out.println("\nmapOfMaxValues...\n");
printMap(mapOfMaxValues);
}
//pretty print a map
public static <K, V> void printMap(Map<K, V> map) {
map.entrySet().stream().forEach((entry) -> {
System.out.println("Key : " + entry.getKey()
+ " Value : " + entry.getValue());
});
}
}
// note: only tested with random values provided in the code
// behavior for large maps untested
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.