词频统计器

做一个词频统计程序,该程序具有以下功能
基本要求:
(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);
        	}
        }
          
    }  
  
}  

结果:

词频统计器

选择文件:

词频统计器

词频统计器

界面做的很粗糙,但主要不是做界面,而是分拣算法。