比较HashMap和值

时间:2017-11-16 17:34:26

标签: java hashmap

我有一个HashMap如下 -

HashMap<String, Integer> BC = new HashMap<String, Integer>();

存储为键 - “标记/标记”和值 - “每个标记/标记的频率”。

实施例 -

"the/at" 153
"that/cs" 45
"Ann/np" 3

我现在解析每个键并检查相同的令牌是否说“是”它是否与多个标签相关联,然后取两者中最大的一个。

实施例 -

"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次(加上一些)。

我的问题是 - 我可以使用更有效的方法完成相同的输出吗?

谢谢!

4 个答案:

答案 0 :(得分:2)

制作新的

Map<String,Integer> highCount = new HashMap<>();

会将令牌映射到最大数量。

一键通过。

将每个键拆分为其组件标记。

对于每个令牌,请查看highMap。如果密钥不存在,请添加其计数。如果条目已存在且当前计数大于先前的最大值,则替换地图中的最大值。

完成单次传递后,highCount将包含所有唯一令牌以及每个令牌所见的最高次数。

注意:此答案旨在为您提供开发完整解决方案的起点。关键的概念是,您可以创建一个新地图,从令牌填充到某种“值”类型(不一定只是Integer),为您提供所需的功能。很可能值类型将是一个新的自定义类,用于存储标记和计数。

答案 1 :(得分:0)

当前方法中最慢的部分是由于键的成对比较。首先,定义一个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; 
  } 
} 

因此,你可以尝试一种算法:

  1. 初始化新的HashMap<String, Tuple<String, Integer>> result
  2. 从旧地图中获取输入对(key, value),其中key = "a/b",检查result.keySet().contains(a)result.keySet().contains(b)
  3. 如果ab都不存在,result.put(a, new Tuple<String, Integer>(b, value)result.put(b, new Tuple<String, Integer>(a, value))
  4. 如果存在a,请比较valuev = result.get(a)。如果value > v,请从a移除bresult并执行第3步。对b执行相同操作。否则,获取下一个键值对。
  5. 在遍历旧哈希映射并插入所有内容之后,您可以通过转换result中的键值来轻松地重建所需的输出。

答案 2 :(得分:0)

算法的基本思路:

  1. 您应该获取HashMap的entrySet()并将其转换为List:

    ArrayList<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
    
  2. 现在您应该按字母顺序按键对列表进行排序。我们这样做是因为HashMap没有顺序,因此您可以预期相应的键可能相距很远。但是通过对它们进行排序,所有相关的键都是直接相邻的。

    Collections.sort(list, Comparator.comparing(e -> e.getKey()));
    

    条目&#34; / at&#34;和&#34; / det&#34;由于按字母顺序排序,它们将彼此相邻。

  3. 现在,您可以在记住最佳项目的同时迭代整个列表,直到找到更好的项目,或者找到第一个没有相同前缀的项目(例如&#34;&#34;)。

    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);
    
  4. 现在您应该有一个表示所需条目的Map.Entry对象列表。复杂度应为n(log n)并受排序算法的限制,而对项目进行分组/收集的复杂度为n。

答案 3 :(得分:0)

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