简体   繁体   English

以正确的顺序迭代ConcurrentHashMap

[英]Iterating a ConcurrentHashMap in correct order

I use a ConcurrentHashMap to store English words and their occurrences within a text. 我使用ConcurrentHashMap在文本中存储英语单词及其出现。

private Map<String, Integer> _vocab = new ConcurrentHashMap<String,Integer>();

I need the map to be sorted by the value in descending order, so I did: 我需要将地图按值降序排序,所以我做了:

   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));
    }

Which seems to be working. 这似乎正在工作。 However, now I want to limit the hashmap to for example 1000 elements, since I'm only interested in the top 1000 entries: 但是,现在我想将哈希图限制为例如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;
}

The problem is, that the iterator is not iterating in the correct order, but rather randomly. 问题在于,迭代器的迭代顺序不是正确的,而是随机的。

So I read that only LinkedHashMaps work this way, but since there is no Concurrent version and I'm afraid to do the synchronization myself, I'm wondering if there is any workaround to achieve what I want? 因此,我读到只有LinkedHashMaps可以这样工作,但是由于没有并发版本,而且我害怕自己进行同步,所以我想知道是否有任何变通办法来实现我想要的?

Edit: I used a HashMap because insertion/occurrence counting was very simple: 编辑:我使用了HashMap,因为插入/出现计数非常简单:

for(String word: input){
  this._vocab.put(word, this._vocab.getOrDefault(word, 0)+1);
}

You could just apply limit on the stream: 您可以对流应用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));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM