Java面试题,读取一篇英文文章,输出其中出现单词的次数最多的5个

来源:互联网 发布:淘宝客url转换 编辑:程序博客网 时间:2024/04/30 21:27

       

     这种类型的题,在许多互联网笔试面试中经常会遇到,今天在这详细的说明一下如何实现。具体解释后面有注释

      废话不多说,直接上代码:

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class CountsWord {


public static void main(String[] args) throws Exception {

BufferedReader readfile = new BufferedReader(new FileReader(

"C:\\test.txt"));/*首先将文件的内容读取到缓冲区bufferedreader中,利用

的是BufferedReader中的readline()读取文件中的每一个文本行,readline()并不是一行一行读取的,而是一个文本

行一个文本行读取。什么是文本行?看Java API中BufferedReader类总中的readline()的解释。*/

StringBuffer sb = new StringBuffer();

String text = null;

while ((text = readfile.readLine()) != null) {

sb.append(text);//将从文件中读出来的字符串追加,形成一个字符串
}
readfile.close();
Pattern patten = Pattern.compile("[a-zA-Z]+");/*用Pattern类中的complie()方法,将正则表达式编译到模式中*/
String sbstring = sb.toString();

Matcher matcher = patten.matcher(sbstring);/*用Pattern类中的matcher()方法,生成一个匹配

器对象,Matcher类是匹配器类*/

Map<String, Integer> tp = new TreeMap<String, Integer>();

while (matcher.find()) {/*用Matcher类中的find()方法,查找与模式匹配的下一个子序列*/

String word = matcher.group();/*用Matcher类中的group()方法, 返回匹配的子序列*/

if (tp.containsKey(word)) {//统计每个单词出现的次数

Integer wordfrequency = tp.get(word);

tp.put(word, wordfrequency + 1);

} else {

tp.put(word, 1);

}


}
List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(

tp.entrySet());/*将treemap中的键值对的set视图存入ArrayList中,其中的类

型必须是Map.Entry,因为TreeMap中的entrySet()方法的返回类型就是Map.Entry类型,其实Map.Entry就是个接口。

将treemap存入ArrayList的目的就是用Collections类中的sort()方法进行排序,其中的sort(List<T>

 list,Comparator)是按照指定的比较器进行排序*/

Comparator<Map.Entry<String, Integer>> comparator = new Comparator<Map.Entry<String,

 Integer>>() {/*重写Comparator比较器,目的是让TreeMap按照value进行降序排列,这里的重写比较器用的是匿名

类,也就是是先创建实现Comparator接口的类,并重写其中的compare方法,并不是接口实例化了。如果觉得用匿名

类这种方式实现比较器重写,你还可以单独写个类MyComparator实现接口Comparator,并重写compare()方法,在

sort(List<T>list,new MyComparator())作用一样*/

     public int compare(Map.Entry<String, Integer> param1,Map.Entry<String, Integer> param2) {

            return (param2.getValue().compareTo(param1.getValue());/*如果是实现升序就是return (param1.getValue().compareTo(param2.getValue());具体解释看下面的解释*/

}
};
Collections.sort(list, comparator);//按照指定的比较器,对list列表进行升序或者降序排序

for (int i = 0; i < 5; i++) {
String key = list.get(i).getKey();
Integer value = list.get(i).getValue();
System.out.println(key + ":" + value);
}
}
}


   可能有些人对重写比较器Comparator和sort()如何完成排序的有些疑惑,这里就我个人观点进行说明,如有不对

的地方,还请大家指正。比较器中的compare方法只是负责将两个参数比较的结果返回,并不负责进行排序。进行排

序的是sort()方法,它根据compare()方法的返回值进行相应排序。第一个参数小于第二个参数 返回负数 ;第一个

参数大于第二个参数 返回正数;第一个参数等于第二个参数 返回0。

   java的api中这个方法

   sort(List <T> list, Comparator <? super T> c)

   api的解释是:根据指定比较器产生的顺序对指定列表进行排序。

  Comparator里的compare方法在api里解释是:比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个

参数分别返回负整数、零或正整数。

  问题:重写Comparator里的compare方法,compare根据传进去的两个对象进行对比后返回一个整数,compare只是

返回了一个整数来表明<,=,>,但是并没有根据compare的返回结果对这两个对象进行某种排序,那么最后比较器是

怎么产生顺序的?

    sort方法怎么实现,可以查看源码

    但是一般思路都是从升序开始(可能人的意识是看到排序最初的印象是升序),但是因为sort本身是个模板,也

就是希望sort不改变,由用户传入的比较器来决定排序,所以6L的伪代码就是基于升序的基础去处理的,sort里面只

需要关心比较器的返回值,如果返回值大于0,则说明比较参数1大于比较参数2,则把参数1"沉底"(换过来说就是参

数2冒泡),这样当用户改变比较器,原本参数1大于参数2应该返回大于0的,可用户却故意返回小于0,这样相当于

比较器欺骗了sort,sort因为只关心结果,于是就认为参数2大于参数1,于是把参数2"沉底"(参数1冒泡),这样就

相当于把“小”的放到最底,于是也就成了“降序”排序。

    所以,排序的模板一般来说都是基于升序实现的,如果要达到“降序”,就由用户去实现比较器然后传给sort方法就可以了


0 0
原创粉丝点击