以正确的顺序迭代ConcurrentHashMap

net*_*tik 2 java data-structures

我用a ConcurrentHashMap来存储英文单词及其在文本中的出现次数.

private Map<String, Integer> _vocab = new ConcurrentHashMap<String,Integer>();
Run Code Online (Sandbox Code Playgroud)

我需要按降序对值进行排序,所以我做了:

   public void sort(){
        this._vocab = this._vocab.entrySet()
                .stream()
                .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
                .collect(
                        toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,
                                LinkedHashMap::new));
    }
Run Code Online (Sandbox Code Playgroud)

这似乎有效.但是,现在我想将hashmap限制​​为例如1000个元素,因为我只对前1000个条目感兴趣:

public void limitToNElements(int n){
    ConcurrentHashMap<String, Integer> res = new ConcurrentHashMap<String, Integer>();

    Iterator it = this._vocab.entrySet().iterator();
    int i = 0;
    while (it.hasNext() && i < n) {
        Map.Entry pair = (Map.Entry)it.next();
        String word = (String)pair.getKey();
        res.put((String)pair.getKey(), (Integer)pair.getValue());

        i += 1;
    }

    this._vocab = res;
}
Run Code Online (Sandbox Code Playgroud)

问题是,迭代器不是以正确的顺序迭代,而是随机迭代.

所以我读到只有这样LinkedHashMaps工作,但由于没有Concurrent版本,我害怕自己做同步,我想知道是否有任何解决方法来实现我想要的?

编辑:我使用了HashMap,因为插入/发生计数非常简单:

for(String word: input){
  this._vocab.put(word, this._vocab.getOrDefault(word, 0)+1);
}
Run Code Online (Sandbox Code Playgroud)

Mur*_*nik 5

你可以limit在流上申请:

public void sort() {
    this._vocab = this._vocab.entrySet()
            .stream()
            .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
            .limit(1000) // Here
            .collect(
                    toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,
                            LinkedHashMap::new));
}
Run Code Online (Sandbox Code Playgroud)

  • 这似乎主要掩盖了基本的问题,即在排序之后,考虑到海报的目标,结果被莫名其妙地再次破坏回到地图中,没有特别的原因. (2认同)