Java 如何获取给定文本中N个最常用的单词,从最大值到最小值排序?

Java 如何获取给定文本中N个最常用的单词,从最大值到最小值排序?,java,sorting,map,word,alphabetical,Java,Sorting,Map,Word,Alphabetical,我得到了一个大文本作为输入。我制作了一个HashMap,它将每个不同的单词存储为一个键,并将出现的次数存储为value(整数) 现在我必须创建一个名为mostOften(int k):List的方法,该方法返回一个列表,该列表使用我之前制作的HashMap,给出从最大出现次数到最小出现次数(降序)的第一个k字。 问题是,每当两个单词出现的次数相同时,它们就应该按字母顺序排序 我想到的第一个想法是交换给定HashMap的键和值,并将其放入TreeMap,TreeMap将按键(整数-单词出现的次数)

我得到了一个大文本作为输入。我制作了一个HashMap,它将每个不同的单词存储为一个键,并将出现的次数存储为value(整数)

现在我必须创建一个名为mostOften(int k):List的方法,该方法返回一个列表,该列表使用我之前制作的HashMap,给出从最大出现次数到最小出现次数(降序)的第一个k字。 问题是,每当两个单词出现的次数相同时,它们就应该按字母顺序排序

我想到的第一个想法是交换给定HashMap的键和值,并将其放入TreeMap,TreeMap将按键(整数-单词出现的次数)对单词进行排序,然后从TreeMap中弹出最后/第一个K项

但当2或3个单词的数量相同时,我肯定会有冲突。我将按字母顺序比较单词,但第二个单词comming的关键字应该是什么整数

如何实现此功能或其他选项,您有何想法?

提示:

  • 查看javadocs中的
    集合。sort
    方法。。。他们两个

  • 查看javadocs中的
    Map.entries()

  • 想一想如何实现一个比较器,该比较器将一个类的实例与两个字段进行比较,当另一个字段比较相等时,将第二个字段用作“平局断路器”


  • 这是我提出的解决方案

  • 首先,创建一个类
    MyWord
    ,该类可以存储单词的
    String
    值及其出现的次数
  • 您实现了该类的
    Comparable
    接口,以便首先按事件排序,如果事件数相同,则按字母顺序排序
  • 然后,对于最常用的方法,您可以从原始的
    映射
    创建一个新的
    列表
    。您可以将此项添加到
    列表中
  • 你可以把这个列表排序吗
  • 使用
    子列表
  • 将这些
    字符串
    添加到
    列表
    并返回它

  • 公共类测试{
    公共静态void main(字符串[]args){
    Map m=新的HashMap();
    m、 放入(“你好”,5);
    m、 放置(“光环”,5);
    m、 放入(“本”,2);
    m、 放("该",2);;
    m、 付诸表决(“良好”,1);
    系统输出println(mostOften(m,3));
    }
    公共静态列表mostOften(地图m、int k){
    列表l=新的ArrayList();
    对于(Map.Entry:m.entrySet())
    l、 添加(新的MyWord(entry.getKey(),entry.getValue());
    集合。排序(l);
    列表=新的ArrayList();
    for(MyWord w:l.子列表(0,k))
    列表。添加(w.word);
    退货清单;
    }
    }
    类MyWord实现了可比较的{
    公共字符串;
    公共事件;
    公共MyWord(字符串字,整数出现){
    超级();
    这个单词=单词;
    this.occurrence=occurrence;
    }
    @凌驾
    公共整数比较(MyWord arg0){
    int cmp=Integer.compare(arg0.occurrence,this.occurrence);
    返回cmp!=0?cmp:word.compareTo(arg0.word);
    }
    @凌驾
    公共int hashCode(){
    最终整数素数=31;
    int结果=1;
    结果=主要*结果+发生;
    result=prime*result+((word==null)?0:word.hashCode();
    返回结果;
    }
    @凌驾
    公共布尔等于(对象obj){
    if(this==obj)
    返回true;
    if(obj==null)
    返回false;
    如果(getClass()!=obj.getClass())
    返回false;
    MyWord other=(MyWord)obj;
    如果(发生!=其他发生)
    返回false;
    if(word==null){
    if(other.word!=null)
    返回false;
    }else如果(!word.equals(other.word))
    返回false;
    返回true;
    }   
    }
    

    输出:
    [halo,hello,that]
    除了您的
    地图
    存储字数之外,我将使用固定大小K的
    优先队列
    (自然顺序)。它将允许达到O(N)复杂度。以下是使用此方法的代码:

    在构造函数中,我们逐字读取输入流,并填充映射中的计数器

    同时,我们正在更新优先级队列,使其保持最大大小=K(我们需要计算前K个字)

    公共类TopnWordsCenter
    {
    公共静态类字数
    {
    字符串字;
    整数计数;
    公共字计数(字符串字)
    {
    这个单词=单词;
    这个.count=1;
    }
    }
    专用优先队列pq;
    私有地图dict;
    公共TopnWordsCenter(扫描仪)
    {
    pq=新的优先级队列(10,新的比较器()
    {
    @凌驾
    公共整数比较(字数o1,字数o2)
    {
    返回o2.count-o1.count;
    }
    });
    dict=newhashmap();
    while(scanner.hasNext())
    {
    字符串字=scanner.next();
    WordCount wc=dict.get(word);
    如果(wc==null)
    {
    wc=新字数(字);
    dict.put(单词,wc);
    }
    如果(pq.包含(wc))
    {
    pq.移除(wc);
    wc.count++;
    pq.add(wc);
    }
    其他的
    {
    wc.count++;
    如果(pq.size()<10 | | wc.count>=pq.peek().count)
    {
    pq.add(wc);
    }
    }
    如果(pq.size()>10)
    {
    pq.poll();
    }
    }
    }
    公共列表getoptenwords()
    {
    堆栈topTen=新堆栈();
    而(!pq.isEmpty())
    {
    添加(pq.poll().word);
    }
    返回前十名;
    }
    }
    
    您在什么环境下使用此功能?是自动完成预测吗?某种:):):)
    public class Test {
        public static void main(String [] args){
            Map<String, Integer> m = new HashMap<>();
            m.put("hello",5);
            m.put("halo",5);
            m.put("this",2);
            m.put("that",2);
            m.put("good",1);
            System.out.println(mostOften(m, 3));
        }
    
        public static List<String> mostOften(Map<String, Integer> m, int k){
            List<MyWord> l = new ArrayList<>();
            for(Map.Entry<String, Integer> entry : m.entrySet())
                l.add(new MyWord(entry.getKey(), entry.getValue()));
    
            Collections.sort(l);
            List<String> list = new ArrayList<>();
            for(MyWord w : l.subList(0, k))
                list.add(w.word);
            return list;
        }
    }
    
    class MyWord implements Comparable<MyWord>{
        public String word;
        public int occurence;
    
        public MyWord(String word, int occurence) {
            super();
            this.word = word;
            this.occurence = occurence;
        }
    
        @Override
        public int compareTo(MyWord arg0) {
            int cmp = Integer.compare(arg0.occurence,this.occurence);
            return cmp != 0 ? cmp : word.compareTo(arg0.word);
        }
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + occurence;
            result = prime * result + ((word == null) ? 0 : word.hashCode());
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            MyWord other = (MyWord) obj;
            if (occurence != other.occurence)
                return false;
            if (word == null) {
                if (other.word != null)
                    return false;
            } else if (!word.equals(other.word))
                return false;
            return true;
        }   
    
    }
    
    public class TopNWordsCounter
    {
    
    public static class WordCount
    {
        String word;
        int count;
    
        public WordCount(String word)
        {
            this.word = word;
            this.count = 1;
        }
    }
    
    private PriorityQueue<WordCount> pq;
    private Map<String, WordCount> dict;
    
    public TopNWordsCounter(Scanner scanner)
    {
        pq = new PriorityQueue<>(10, new Comparator<WordCount>()
        {
            @Override
            public int compare(WordCount o1, WordCount o2)
            {
                return o2.count-o1.count;
            }
        });
        dict = new HashMap<>();
    
        while (scanner.hasNext())
        {
            String word = scanner.next();
    
            WordCount wc = dict.get(word);
            if (wc == null)
            {
                wc = new WordCount(word);
                dict.put(word, wc);
            }
    
            if (pq.contains(wc))
            {
                pq.remove(wc);
                wc.count++;
                pq.add(wc);
            }
            else
            {
                wc.count++;
                if (pq.size() < 10 || wc.count >= pq.peek().count)
                {
                    pq.add(wc);
                }
            }
    
            if (pq.size() > 10)
            {
                pq.poll();
            }
        }
    }
    
    public List<String> getTopTenWords()
    {
        Stack<String> topTen = new Stack<>();
        while (!pq.isEmpty())
        {
            topTen.add(pq.poll().word);
        }
        return topTen;
    }
    
    
    }