使用Java記錄四級試卷中的單詞出現頻率
阿新 • • 發佈:2018-11-17
1. 前言
實現的功能是,記錄四級試卷中所有單詞出現頻率,並將單詞以頻率高低的方式進行排序,當然不僅是試卷,其他的文章都可以
2. 思路
怎麼使用Java記錄一張四級卷子裡中所有的單詞呢
-
讀取到文章所有的內容
-
區分單詞與其他字元,用
map
將單詞與出現次數建立對映 -
將
map
排序
3. 實現
3.1 讀取文章所有內容
首先在網上下載四級卷子的word版,將其內容複製到txt文字
中,我們使用Java讀取這個txt文字
裡的所有內容
使用的是Java 7
中新增的NIO
包中的Files
類和Path
類來讀取檔案,非常方便,確保JDK版本在1.7以上
// 引數填上需要讀取檔案的路徑
Path path = Paths.get("D:\code\words\2015年6月.txt");
BufferedReader br = Files.newBufferedReader(path);
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
3.2 區分單詞與其他字元,用map將單詞與出現次數建立對映
一開始想使用正則的方法來將單詞拆分,但發現會比較麻煩,因為單詞拆分原則比較多,有空格,有括號,引號以及句號等等
還有一個重要原因是因為,我想把單詞第一個大寫的字母轉換為小寫,這樣在統計頻率的時候,會更加利於我們操作
所以採用了下面的方法
while ((line = br.readLine()) != null) {
StringBuilder word = new StringBuilder();
for (int j = 0; j < line.length(); j++) {
char ch =line.charAt(j);
if (ch >= 'a' && ch <= 'z') {
word.append(ch);
} else if (ch >= 'A' && ch <= 'Z') { // 如果單詞是大寫,把它轉換為小寫形式,方便統計次數
word.append((char) (ch + 32));
} else if (word.toString().length() > 1) {// 如果遇到不是單詞的字元,而且單詞不是一個字母
String word_string = word.toString();
// 如果單詞不存在, 將單詞填入並初始化為1次
if (!map.containsKey(word_string)) {
map.put(word_string, 1);
} else {
// 如果單詞存在,找到該單詞對應的頻率,將其加1,重新覆蓋
map.put(word_string, map.get(word_string) + 1);
}
// 清空StringBuilder, 計入下個單詞
word.setLength(0);
}
}
}
3.3 將map排序
用到Collections.sort()
方法和map的內部介面Map.Entry
Map.Entry
是map的一個內部介面,它表示map的一個實體(也就是一個key-value
對)
用以下方法可以實現,將Map按value以降序的方式排序
List<Map.Entry<String, Integer>> infoIds = new ArrayList<>(map.entrySet());
Collections.sort(infoIds, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return (o2.getValue() - o1.getValue());
}
});
4. 程式碼
以下是實現的總程式碼,可計算多張卷子
package indi.zmj.corejava.bit;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
/**
* @author zmj
* @create 2018/11/11
*/
public class splitWords {
public void readPapers(String[] url) throws IOException {
TreeMap<String, Integer> map = new TreeMap<>();
for (int i = 0; i < url.length; i++) {
Path path = Paths.get(url[i]);
BufferedReader br = Files.newBufferedReader(path);
String line = null;
// 讀取檔案中的每一行, 並用StringBuilder統計每個單詞
while ((line = br.readLine()) != null) {
StringBuilder word = new StringBuilder();
for (int j = 0; j < line.length(); j++) {
char ch = line.charAt(j);
if (ch >= 'a' && ch <= 'z') {
word.append(ch);
} else if (ch >= 'A' && ch <= 'Z') {
// 如果單詞是大寫,把它轉換為小寫形式,方便統計次數
word.append((char) (ch + 32));
} else if (word.toString().length() > 1) {
String word_string = word.toString();
// 如果單詞不存在, 將單詞填入並初始化為1次
if (!map.containsKey(word_string)) {
map.put(word_string, 1);
} else {
// 如果單詞存在,找到該單詞對應的頻率,將其加1,重新覆蓋
map.put(word_string, map.get(word_string) + 1);
}
// 清空StringBuilder, 計入下個單詞
word.setLength(0);
}
}
}
br.close();
}
List<Map.Entry<String, Integer>> infoIds = new ArrayList<>(map.entrySet());
Collections.sort(infoIds, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return (o2.getValue() - o1.getValue());
}
});
for (int i = 0; i < infoIds.size(); i++) {
System.out.printf("單詞:%12s 出現了:%d次\n", infoIds.get(i).getKey(), infoIds.get(i).getValue());
}
}
public static void main(String[] args) throws IOException {
String[] url = {"D:\\code\\words\\2015年6月.txt", "D:\\code\\words\\2015年12月.txt"
, "D:\\code\\words\\2016年6月.txt", "D:\\code\\words\\2016年12月.txt",
"D:\\code\\words\\2017年12月.txt", "D:\\code\\words\\2018年6月.txt"};
new splitWords().readPapers(url);
}
}
5. 效果圖
截取了其中一部分效果