要求:
写一个程序,分析一个文本文件中各个词出现的频率,并且把频率最高的10个词打印出来。文本文件大约是30KB~300KB大小。
解决步骤:
1、读取一个 txt 文本文件;
2、统计文件里面每个词出现的次数;
3、进行排序,打印出频率最高的10个词。
编程语言 :java;
测试文本 :F:\\测试文件.txt 大小:2.00 KB (2,053 字节)
性能测试工具 :JDK自带的 Visualvm插件
初步思路:
1、将文件内容存放在bf(StringBuffer )里面;
2、将bf转换成字符串str,并把字符串str匹配到matcher里
3、一个一个匹配matcher中的字符串,将其放入 Map<String,Integer> 中,key=词,value=出现次数;
4、对Map 进行排序,得到出现频率最高的10个词;
程序实现:
package task1;
/*1、作业1
* 2、实现功能:写一个程序,分析一个文本文件中各个词出现的频率,
* 并且把频率最高的10个词打印出来。
* 3、作者:彭瑶
* */
importjava.io.BufferedReader;
importjava.util.Comparator;
importjava.util.List;
importjava.util.Map;
importjava.util.TreeMap;
importjava.io.FileReader;
importjava.util.ArrayList;
importjava.util.Collections;
importjava.util.regex.Matcher;
importjava.util.regex.Pattern;
public classDemo1 {
/**
*@param args
*/
public static void main(String[]args)throws Exception {
//TODO Auto-generated method stub
long time1 =System.currentTimeMillis();
BufferedReader rd = newBufferedReader(new FileReader(
"F:\\测试文件.txt"));
StringBuffer bf = new StringBuffer();
String line = null;
while ((line = rd.readLine()) != null){
//把读出来的文件放到bf里面
bf.append(line);
}
rd.close();
Pattern aa =Pattern.compile("[a-zA-Z]+");// 定义正则表达式匹配单词
String string = bf.toString();
Matcher match = aa.matcher(string);//
Map<String, Integer> map = newTreeMap<String, Integer>();
String word = "";
int times = 0;
// 是否匹配单词
while (match.find()) {
// 得到一个单词-树映射的键
word = match.group();
// 如果包含该键,单词出现过
if (map.containsKey(word)) {
times = map.get(word);// 得到单词出现的次数
map.put(word, times + 1);
}
else
{
map.put(word, 1);// 否则单词第一次出现,添加到映射中
}
}
/*
* 重点:按照TreeMap 的value排序而不是key排序。
* 做法:将Map.Entry放在集合里,重写比较器,在用
* Collections.sort(list, comparator)进行排序
*/
List<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String, Integer>>(
map.entrySet());
/*
* 重写比较器
* 取出单词个数(value)比较
*/
Comparator<Map.Entry<String,Integer>> comparator = new Comparator<Map.Entry<String,Integer>>() {
public intcompare(Map.Entry<String, Integer> left,
Map.Entry<String,Integer> right) {
return(left.getValue()).compareTo(right.getValue());
}
};
Collections.sort(list, comparator);// 排序
// 输出
int num = list.size() - 1;
int i=num;
do
{
String key = list.get(i).getKey();
Integer value =list.get(i).getValue();
System.out.print("Top"+(num-i+1)+" : ");
System.out.println(key + "" + value);
i--;
}
while(i > num-10);
long time2 =System.currentTimeMillis();
System.out.println("耗时:");
System.out.println(time2 -time1+"ms");
}
}
运行结果1:
不足与改进:
出现的高频单词大多数都是冠词、介词、连接词等,不是能表达文章内容的关键词,改进程序,通过条件判断语句让冠词、介词、连接词等不出现在结果中。
改进后的程序:
package task1;
/*1、作业1
* 2、实现功能:写一个程序,分析一个文本文件中各个词出现的频率,
* 并且把频率最高的10个词打印出来。
* 3、作者:彭瑶
* */
importjava.io.BufferedReader;
importjava.util.Comparator;
importjava.util.List;
importjava.util.Map;
importjava.util.TreeMap;
importjava.io.FileReader;
importjava.util.ArrayList;
importjava.util.Collections;
importjava.util.regex.Matcher;
importjava.util.regex.Pattern;
public classDemo1 {
/**
*@param args
*/
public static void main(String[]args)throws Exception {
// TODO Auto-generated method stub
long time1 =System.currentTimeMillis();
BufferedReader rd = newBufferedReader(new FileReader(
"F:\\测试文件.txt"));
StringBuffer bf = new StringBuffer();
String line = null;
while ((line = rd.readLine()) != null){
//把读出来的文件放到bf里面
bf.append(line);
}
rd.close();
Pattern aa =Pattern.compile("[a-zA-Z]+");// 定义正则表达式匹配单词
String str = bf.toString();
Matcher match =aa.matcher(str);//快速匹配整个字符串str到match中
Map<String, Integer> map = newTreeMap<String, Integer>();
String word = "";
int times = 0;
// 是否匹配单词
while (match.find()) {
word = match.group();// 得到一个单词-树映射的键
if (map.containsKey(word)) // 如果包含该键,单词出现过
{
times = map.get(word);// 得到单词出现的次数
map.put(word, times + 1);
}
else
{
map.put(word, 1);// 否则单词第一次出现,添加到映射中
}
}
/*
* 重点:按照TreeMap 的value排序而不是key排序。
* 做法:将Map.Entry放在集合里,重写比较器,在用
* Collections.sort(list, comparator)进行排序
*/
List<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String, Integer>>(
map.entrySet());
/*
* 重写比较器
* 取出单词个数(value)比较
*/
Comparator<Map.Entry<String,Integer>> comparator = new Comparator<Map.Entry<String,Integer>>() {
public intcompare(Map.Entry<String, Integer> left,
Map.Entry<String,Integer> right) {
return(left.getValue()).compareTo(right.getValue());
}
};
Collections.sort(list, comparator);// 排序
// 输出
int num = list.size() - 1;
for (int i = num,k=0;i>0&k<10 ; i--){
String key = list.get(i).getKey();
//去掉常用的冠词、介词、连接词、代词,得到关键字
if(key.equals("a")||key.equals("an")||key.equals("the")||key.equals("To")||key.equals("on")){
continue;
}
elseif(key.equals("in")||key.equals("to")||key.equals("at")||key.equals("of")){
continue;
}
else if(key.equals("and")||key.equals( "as")||key.equals("be")||key.equals( "with")){
continue;
}
elseif(key.equals("I")||key.equals("are")||key.equals("my")||key.equals("is")||key.equals("am")){
continue;
}
else{
k++;
Integer value = list.get(i).getValue();
System.out.print("Top"+k+" : ");
System.out.println(key + "" + value);
}
}
long time2 =System.currentTimeMillis();
System.out.println("耗时:");
System.out.println(time2 -time1+"ms");
}
}
运行结果2:
结果对比:
结果2出现的关键词比结果1多。
性能测试:
程序运行前:
改进前的程序:
改进后的程序:
改进前程序占的CPU:
改进后程序占的CPU:
Class(改进前):
Class(改进后):
线程(改进前):
线程(改进后):
内存(改进后):
内存(改进前):