Java 类似HashMap但已排序?

Java 类似HashMap但已排序?,java,hashmap,Java,Hashmap,我正在编写一个Java程序,它解析文本文件中的所有单词,然后将它们添加到HashMap中。我需要计算文件中包含多少不同的单词。我还需要计算出计数最高的单词。HashMap由映射到整数的每个单词组成,整数表示单词出现的次数 是否有类似HashMap的东西可以帮助我对其进行排序?看起来库中的TreeBag类可以满足您的需要。它跟踪一个对象添加到包中的副本数量,并按计数的升序对它们进行排序。要获得最高计数项,只需调用last()方法。需要注意的一点是,commons collections的内容尚未更

我正在编写一个Java程序,它解析文本文件中的所有单词,然后将它们添加到HashMap中。我需要计算文件中包含多少不同的单词。我还需要计算出计数最高的单词。HashMap由映射到整数的每个单词组成,整数表示单词出现的次数


是否有类似HashMap的东西可以帮助我对其进行排序?

看起来库中的
TreeBag
类可以满足您的需要。它跟踪一个对象添加到包中的副本数量,并按计数的升序对它们进行排序。要获得最高计数项,只需调用
last()
方法。需要注意的一点是,commons collections的内容尚未更新为使用泛型,因此使用它可能会收到大量编译器警告。

手动方法如下:

  • 创建一个包含
    word
    count
    字段的复合WordCount类
  • 为该类创建一个按计数排序的比较器
  • 填充完HashMap后,创建一个新的WordCount对象列表,这些对象是根据HashMap中的值创建的
  • 使用比较器对列表进行排序
您可以从以下位置使用HashMultiset:

import com.google.common.collect.*;
导入com.google.common.collect.Multiset.Entry;
...
final Multiset words=HashMultiset.create();
单词。addAll(…);
按递增计数排序=新排序(){
@覆盖公共整数比较(条目a、条目b){
//安全,因为计数从不为负
返回left.getCount()-right.getCount();
}
});
Entry maxEntry=byIncreasingCount.max(words.entrySet())
返回maxEntry.getElement();
编辑:哎呀,我以为你只想要一个最常用的词。但是听起来您需要几个最常见的条目,因此,您可以将
max
替换为
sortedCopy
,现在您有了一个按顺序排列的所有条目的列表

要查找不同字数,请执行以下操作:
words.elementSet().size()

  • YourBean实现了可比较的
  • 方法比较:按字数排序
  • 树映射而不是hashmap

对于计数,将单词塞进一组,并在完成时计算大小


对于最高值,迭代所有条目并按住具有最高值的键。

如果要按单词对映射进行排序,则TreeMap是Java内置的答案。您可以确保Word对象具有可比性,也可以提供自定义比较器

SortedMap<Word,Integer> map = new TreeMap<Word,Integer>();
...
for all words {
    Integer count = map.get(word);
    if (count == null ) count = 0;
    map.put(word, count+1);
}
SortedMap=newtreemap();
...
不言而喻{
整数计数=map.get(word);
如果(count==null)count=0;
map.put(单词,计数+1);
}

如果你想按频率排序,那么在计算完所有单词后,你最好这样做。已排序的集合不会因为外部更改而导致其排序混乱。按频率排序需要一个复合的word+count对象,正如其他人发布的那样。

您签出java.util.PriorityQueue了吗?PriorityQueue基本上是一个列表,其优先级映射到每个元素(由非同步优先级堆实现)。每次读入一个新字符串时,可以将其添加进去,或者如果它已经存在,则将其优先级增加1(对数时间)。当前检查是线性时间的,最终这将非常容易使用。要获得出现频率最高的数字,完成后只需对每个数字进行poll()


编辑标准优先级队列不允许您直接编辑优先级,因为它需要一个比较器。您最好使用一个简单的散列实现或其他什么

以下是一个Groovy版本的最流行答案:

List leastCommon(Multiset myMultiset, Integer quantity)
{

    Ordering<Multiset.Entry<String>> byIncreasingCount = new Ordering<Multiset.Entry<String>>() {
      @Override public int compare(Multiset.Entry<String> a, Multiset.Entry<String> b) {
          return a.getCount() - b.getCount() }
    }

    maxIndex = Math.min(quantity, myMultiset.entrySet().size() - 1)
    return byIncreasingCount.sortedCopy(myMultiset.entrySet()).subList(0, maxIndex)

}

List mostCommon(Multiset myMultiset, Integer quantity)
{

    Ordering<Multiset.Entry<String>> byDecreasingCount = new Ordering<Multiset.Entry<String>>() {
      @Override public int compare(Multiset.Entry<String> a, Multiset.Entry<String> b) {
          return b.getCount() - a.getCount() }
    }

    maxIndex = Math.min(quantity, myMultiset.entrySet().size() - 1)
    return byDecreasingCount.sortedCopy(myMultiset.entrySet()).subList(0, maxIndex)

}
List leastCommon(Multiset myMultiset,整数数量)
{
按递增计数排序=新排序(){
@覆盖公共整数比较(Multiset.Entry a、Multiset.Entry b){
返回a.getCount()-b.getCount()}
}
maxIndex=Math.min(数量,myMultiset.entrySet().size()-1)
通过递增Count.sortedCopy(myMultiset.entrySet())返回。子列表(0,maxIndex)
}
列出最常见的(多集myMultiset,整数数量)
{
按递减计数排序=新排序(){
@覆盖公共整数比较(Multiset.Entry a、Multiset.Entry b){
返回b.getCount()-a.getCount()}
}
maxIndex=Math.min(数量,myMultiset.entrySet().size()-1)
通过DecreasingCount.sortedCopy(myMultiset.entrySet())返回。子列表(0,maxIndex)
}

据我所知,没有一个标准系列可以解决这个问题。有多少个单词?如果你能忍受这样的开销,最容易实现的方法就是使用HashMap,然后将单词和出现的情况放在一个列表中并对其进行排序。想想看,我在大学里得到了这个精确的作业,我们必须用nlog(n)来解决它。我上面的建议解决了这个问题。你想按单词还是按频率对地图进行排序?珍妮,请不要忘记接受答案。或者你可以在谷歌收藏中搜索一些特殊的地图,它们使用泛型。请重新阅读文档。我相信在这种情况下,袋子仍然会按照“关键字”或单词进行分类。不是伯爵。你能引用其他说明的文档吗?你可能是对的,我解释了最后一个方法的描述,表示它返回了计数最大的项,但考虑到可选比较器的上下文,它可能只是指自然顺序最大的项。树映射不能按值排序!因此,这不是正确的数据结构。这使地图中的单词按字典顺序排序,但不幸的是,它们根本没有按频率排序。
List leastCommon(Multiset myMultiset, Integer quantity)
{

    Ordering<Multiset.Entry<String>> byIncreasingCount = new Ordering<Multiset.Entry<String>>() {
      @Override public int compare(Multiset.Entry<String> a, Multiset.Entry<String> b) {
          return a.getCount() - b.getCount() }
    }

    maxIndex = Math.min(quantity, myMultiset.entrySet().size() - 1)
    return byIncreasingCount.sortedCopy(myMultiset.entrySet()).subList(0, maxIndex)

}

List mostCommon(Multiset myMultiset, Integer quantity)
{

    Ordering<Multiset.Entry<String>> byDecreasingCount = new Ordering<Multiset.Entry<String>>() {
      @Override public int compare(Multiset.Entry<String> a, Multiset.Entry<String> b) {
          return b.getCount() - a.getCount() }
    }

    maxIndex = Math.min(quantity, myMultiset.entrySet().size() - 1)
    return byDecreasingCount.sortedCopy(myMultiset.entrySet()).subList(0, maxIndex)

}