1. 程式人生 > >使用Java記錄四級試卷中的單詞出現頻率

使用Java記錄四級試卷中的單詞出現頻率

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. 效果圖

截取了其中一部分效果
在這裡插入圖片描述