词频统计器
做一个词频统计程序,该程序具有以下功能
基本要求:
(1)可导入任意英文文本文件
(2)统计该英文文件中单词数和各单词出现的频率(次数),并能将单词按字典顺序输出。
(3)将单词及频率写入文件。
提高要求:
完成基本要求的基础上,实现下述功能:
1.实现GUI界面。
2.将单词及频率写入数据库。
实现思路:
定义一个单词容器类wordcol,有两个属性,第一个属性为单词本身,第二属性就是出现次数。用一个map来统计,map的key为单词本身,value为wordcol对象。先将一篇文章清洗干净,过滤掉所有的标点符合等,这个用正则表达式即可。然后将大写的字母小写,因为大写和小写不形象单词本身的出现次数,再将单词按照空格分割,分割后得到一个数组就是所有的单词,但是可能包含空格。所以在统计的时候加以判断。
经典分拣思路:
遍历这一堆单词数组,每次取出一个单词,用map的get方法获得value值。如果value为空,则说明,这个单词还没有被统计过,则创建一个新的wordcol,次数为1,然后加入到map中。如果不为空则将获得到的value即wordcol对象中的次数属性加一。加了一个单词首字母排序的功能,即将key进行一个排序,然后按照排序后的key输出,或者直接用treemap。
代码如下:
单词容器类WordCol,用于存放单词和单词次数。
package com.programmingmethed.work;
/**
* 存放单词和词频的类
* @author dengyong
*
*/
public class WordCol {
/**
* 英文单词
*/
private String word;
/**
* 出现的次数
*/
private int count;
public WordCol(String word, int count) {
this.word = word;
this.count = count;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
map统计类:
package com.programmingmethed.work;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class Count {
/**
* 存放单词和词频的map键值对
*/
private Map<String, WordCol> map = new HashMap<>();
/**
* 词频分类表
*/
private Map<Integer, List<String>> classes = new HashMap<>();
/**
* 单词排序表
*/
List<String> keyList;
String mapString = "";
String classesString = "";
public String getMapString() {
return mapString;
}
public String getClassesString() {
return classesString;
}
public List<String> getKeyList() {
return keyList;
}
public Map<String, WordCol> getMap() {
return map;
}
public Map<Integer, List<String>> getClasses() {
return classes;
}
public Count(){
}
public void toCount(String text){
//文本过滤
text = text.toLowerCase().replaceAll( "\\p{Punct}", " " );
// 将文本用空格切分
String [] wordArray = text.split(" ");
// 定义一个单词容器
WordCol wordCol = null;
// 遍历所有的单词数组
for (String word : wordArray) {
// 利用Key获取到value判断是否为空
// 如果为空说明是个新的单词,加入到map中即可
if (word.equals("")) {
continue;
}
if (null == (wordCol = map.get(word))){
wordCol = new WordCol(word, 1);
map.put(word, wordCol); //加入到map中
} else {
// 否则说明该单词已经出现过,在之前的次数上加一
wordCol.setCount(wordCol.getCount()+1);
}
}
}
public void keySorts() {
keyList = new ArrayList<>(map.keySet());
Collections.sort(keyList, new MyComparator()); //将单词进行升序排列
}
public void show(){
mapToText();
classesToText();
System.out.println(mapString);
System.out.println(classesString);
}
public void mapToText() {
if (!mapString.equals("")) {
return;
}
for (String key : keyList) {
String word = map.get(key).getWord(); //取出单词
int count = map.get(key).getCount(); //取出对应的次数
mapString += word + " : " + count+"\r\n";
}
}
public void classesToText() {
if (!classesString.equals("")) {
return;
}
Set<Integer> set = classes.keySet();
for (Integer key : set) {
List<String> words = classes.get(key);
classesString += ("出现" + key + "次的单词有:"+"\r\n");
for (String word : words) {
classesString += (word + " ");
}
classesString += "\r\n";
}
}
public void save(String path, String text) {
File out = new File(path);
BufferedWriter bw;
try {
bw = new BufferedWriter(new FileWriter(out));
bw.write(text);
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读文本文件进行统计
* @param path 文件路径
*/
public void readTxt(String path) {
File src = new File(path);
BufferedReader br = null;
String line = null;
try {
br = new BufferedReader(new FileReader(src));
while (null != (line = br.readLine())) {
toCount(line);
}
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
keySorts();
mapToText();
classesToText();
}
/**
* 词频分类
* 根据单词的次数将单词进行分类
*/
public void sort() {
for (String key : keyList) {
WordCol wordCol = map.get(key);
int count = wordCol.getCount();
String word = wordCol.getWord();
List<String> list = null;
if (null == (list = classes.get(count))) {
list = new ArrayList<>();
list.add(word);
classes.put(count, list);
} else {
list.add(word);
}
}
}
// 字符串比较大的内部类
class MyComparator implements Comparator<String>{
public int compare(String o1, String o2) {
return o1.compareTo(o2);//升序排列
}
}
}
UI界面:
package com.programmingmethed.work;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;
@SuppressWarnings("serial")
public class FileChooser extends JFrame implements ActionListener{
JButton open = new JButton();
JButton save = new JButton();
private JTextArea msgArea = new JTextArea();
private JPanel jpn_Info = new JPanel();
private JScrollPane scrollPane;
public static void main(String[] args) {
new FileChooser();
}
public FileChooser(){
this.setSize(500, 600);
this.setLocationRelativeTo(null);
this.setTitle("单词计数器");
this.setLayout(null);
setJbt();
setMsgArea();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
open.addActionListener(this);
save.addActionListener(this);
}
public void setJbt() {
open.setBounds(390, 50, 80, 30);
open.setText("统计");
this.add(open);
save.setBounds(390, 150, 80, 30);
save.setText("保存");
this.add(save);
}
//设置显示区域
public void setMsgArea() {
msgArea.setLineWrap(true);
msgArea.setEditable(false);
msgArea.setBackground(Color.pink);
msgArea.setFont(new Font("宋体", 1, 18));
jpn_Info = new JPanel();
jpn_Info.setBorder(new EmptyBorder(5,5,5,5));
jpn_Info.setLayout(new BorderLayout(0,0));
scrollPane = new JScrollPane();
jpn_Info.add(scrollPane,BorderLayout.CENTER);
scrollPane.setViewportView(msgArea);
jpn_Info.setBounds(5, 20, 380, 520);
this.add(jpn_Info);
}
public void append(Map<?, ?> map) {
Set<?> set = map.keySet();
for (Object object : set) {
if (object instanceof String) {
WordCol wordCol = (WordCol) map.get((String)object);
msgArea.append(wordCol.getWord() +" : "+wordCol.getCount());
msgArea.append("\r\n");
} else if (object instanceof Integer) {
int i = 0;
@SuppressWarnings("unchecked")
List<String> words = (List<String>) map.get(object);
msgArea.append("出现" + (Integer) object + "次的单词共有:"+ words.size()+"\r\n\r\n");
for (String word : words) {
msgArea.append(word+" ");
i++;
if (i%3 == 0) {
msgArea.append("\r\n");
}
}
msgArea.append("\r\n\r\n");
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser jfc=new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES );
jfc.showDialog(new JLabel(), "选择");
File file=jfc.getSelectedFile();
if (file != null){
Count c = new Count();
if (e.getSource() == open) {
if(file.isFile()){
String path = file.getAbsolutePath();
c.readTxt(path);
c.sort();
Map<Integer, List<String>> classes = c.getClasses();
append(classes);
}
}
if (e.getSource() == save) {
String path = file.getAbsolutePath();
String result = msgArea.getText();
c.save(path, result);
System.out.println(result);
}
}
}
}
结果:
选择文件:
界面做的很粗糙,但主要不是做界面,而是分拣算法。