【java】实现txt文档中汉字频率排序及输出频率最高的前十个汉字

01. 目的

java编程实现统计文档中汉字出现的频率,将汉字出现频率按高频到低频排序,并输出频率最高的前十个汉字。

02. 主要实现方法

(1) 首先按行读出txt文档中的内容:.readLine();

​ 按行读出后取出每行中的字符: .charAt(i);

(2) 构建了HashMap对象,用于存放文档中出现的汉字及其出现的频率。键对应字符,值对应字符出现的次数。

HashMap<Character,Integer> hm = new HashMap<Character,Integer>();

​ 判断汉字是否重复出现(汉字即为map中的键):用map类的containsKey()方法;

​ 取出该键中的值(即汉字出现的频率):.get(key) ;

(3)重写public int compare(Object o1, Object o2) 方法,用Comparator类中的compare(T o1,T o2)对汉字频率比较大小。


可参考博文:【Java】Collections.sort() 方法 —— Comparable、Comparator接口


compare(T o1, T o2)是中的o1,o2代表什么,是怎么实现排序的?怎么和compareTo()配合使用?

​ o1和o2每次只取一个数据,就一次只比较两个数据,假如比较7,8,9,5,6,那么第一次比较o1先取8,o2取7(很奇怪,我当时以为是顺着取值,但是很奇怪,他是相邻两个值逆着取值),接下来配合compareTo()实现这两个数的排序,o1.compareTo(o2)会返回一个int值,如果0说明o1和o2相等,如果返回负值,那么o1和o2会倒序排序,返回正值,那么o1和o2会正序排序。返回值之后这两个值就进行了排序,至此,这两个值已经排序好了,接下来第二次排序,o1取9,o2取8,第三次o1取5,o2取9…

(4)通过entrySet()方法将map集合中的映射关系取出导入List动态数组,用Collections.sort()对值进行排序

(5)使用迭代器Iterator取出map中的键和对应的值。

Iterator<Map.Entry<Character, Integer>> iter = list.iterator();

03. 程序代码(sequence.java)

/* 
* 功能:* 对文档中汉字出现频率进行排序
*       * 在控制台打印频率最高的前十个汉字
* @author WTCLAB_yd
*
*/
import java.io.*;//导入io类包
import java.util.*;//导入util类包
public class sequence {
    public static void main(String[] args){
		File file=new File(args[0]);//建立读入文件对象   
		BufferedReader buf=null;	
        try{
            buf = new BufferedReader(new FileReader(file));//定义字符读取(缓冲)流并赋值
            String value = null; //定义一个临时接收文件中的字符串变量
            String newValue = "";    //接收文件中所有字符串的变量
            while((value = buf .readLine())!=null){
			for(int i=0;i<value.length();i++){//开始读取文件中的字符
			if(value.charAt(i)>=0x4e00 && value.charAt(i)<=0x9fbb){
                newValue = newValue+value.charAt(i);    //存入newValue变量中
            }
			}
			}
            char[] ch = newValue.toCharArray();//把newValue变成字符数组(Collections. reverseOrder())
            HashMap<Character,Integer> hm = new HashMap<Character,Integer>();//构建了一个新的HashMap对象,赋予变量hm.键对应字符,值对应字符出现的次数
            for(int j = 0;j<ch.length;j++){   //遍历ch  将ch中所有的字符存入一个Map集合中,键对应字符,值对应字符出现的次数
                char c = ch[j];
                if(hm.containsKey(c)){  //如果HashMap(hm)中有该键,则取出该键中的值,也就是出现的次数
                    int conut = hm.get(c);//取出该键中的值(该键出现的次数)放入count
                    hm.put(c,conut+1);  //存入把新值存入hm集合中,如果键相同的话, 新键会替换老键,值也随着变化了
                }
                else{
                    hm.put(c, 1);  //如果没有出现该键就说明是第一次出现,然后就存入1次
                }
            }
			//自定义比较器
		Comparator<Map.Entry<Character, Integer>> descValue = new Comparator<Map.Entry<Character,Integer>>(){
			@Override
			public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {// o1和o2每次只取一个数据,就一次只比较两个数据
				int i1 = o1.getValue();	// 获取键的值(即字符对应出现的频率)
				int i2 = o2.getValue();	
				if (i1 != i2) { //若不同字符出现的频率不等,则返回1或-1
					return (i1 > i2) ? -1 : 1;//如果返回负值,那么i1和i2会倒序排序,返回正值,那么i1和i2会正序排序
				} 
				else {
					return 0;//返回0说明i1和i2相等
				}
			}
		};
		//取出map中的键和对应的值
		Set<Map.Entry<Character, Integer>> set = hm.entrySet();//通过entrySet()方法将map集合中的映射关系取出(这个关系就是Map.Entry类型)
		List<Map.Entry<Character, Integer>> list = new ArrayList<Map.Entry<Character, Integer>>(set);//创建一个List的对象,list这个链表中的元素是Map类型的元素
		Collections.sort(list, descValue);//根据比较器返回值对值(频率)排序
		//获得map的迭代器,用作遍历map中的每一个键值对
		Iterator<Map.Entry<Character, Integer>> iter = list.iterator();
		 System.out.print("\n本文中出现次数最高的前十个字: \n");
            for(int n=0;n<10;n++){ //取出迭代器中前十个键值对
                Map.Entry<Character, Integer> map = iter.next();//获得键值对
                char k = map.getKey();//获取map的键(对应文档中的字符)
                int v = map.getValue();//获取键对应的值(字符出现的频率)
                System.out.print("\n   "+k+" ——  "+v );
            }
        }		
        catch(IOException e){
            System.out.println("文件读取错误");
        }
        finally{
            try{
                if(buf!=null)
                    buf.close();//关闭数据流
            }
            catch(IOException e){
                System.out.println("文件关闭错误");
            }
        }
    }
}

04. 结果演示

(1)test.txt 测试

【java】实现txt文档中汉字频率排序及输出频率最高的前十个汉字

【java】实现txt文档中汉字频率排序及输出频率最高的前十个汉字

(2) 西游记测试(xyj.txt)
找出西游记中出现次数最多的十个字:
【java】实现txt文档中汉字频率排序及输出频率最高的前十个汉字

【java】实现txt文档中汉字频率排序及输出频率最高的前十个汉字

05. 补:程序计时

对大文档进行汉字排序时用时较多,为了便于优化程序、对比程序效率,在程序中加计时器打印程序运行时间,便于观察。

程序代码:(TimeCount.java)

添加System.currentTimeMillis()方法

* 功能:* 对文档中汉字出现频率进行排序
*       * 在控制台打印频率最高的前十个汉字
*       *获取程序运行所需时间
* @author WTCLAB_yd
*
*/

import java.io.*;//导入io类包
import java.util.*;//导入util类包
public class TimeCount {
    public static void main(String[] args){
		double begin = System.currentTimeMillis(); // 程序开始时间,调用系统的当前时间,时间单位为毫秒
		File file=new File(args[0]);//建立读入文件对象   
		BufferedReader buf=null;	
        try{
            buf = new BufferedReader(new FileReader(file));//定义字符读取(缓冲)流并赋值
            String value = null; //定义一个临时接收文件中的字符串变量
            String newValue = "";    //接收文件中所有字符串的变量
            while((value = buf .readLine())!=null){
			for(int i=0;i<value.length();i++){//开始读取文件中的字符
			if(value.charAt(i)>=0x4e00 && value.charAt(i)<=0x9fbb){
                newValue = newValue+value.charAt(i);    //存入newValue变量中
            }
			}
			}
            char[] ch = newValue.toCharArray();//把newValue变成字符数组(Collections. reverseOrder())
            HashMap<Character,Integer> hm = new HashMap<Character,Integer>();//构建了一个新的HashMap对象,赋予变量hm.键对应字符,值对应字符出现的次数
            for(int j = 0;j<ch.length;j++){   //遍历ch  将ch中所有的字符存入一个Map集合中,键对应字符,值对应字符出现的次数
                char c = ch[j];
                if(hm.containsKey(c)){  //如果HashMap(hm)中有该键,则取出该键中的值,也就是出现的次数
                    int conut = hm.get(c);//取出该键中的值(该键出现的次数)放入count
                    hm.put(c,conut+1);  //存入把新值存入hm集合中,如果键相同的话, 新键会替换老键,值也随着变化了
                }
                else{
                    hm.put(c, 1);  //如果没有出现该键就说明是第一次出现,然后就存入1次
                }
            }
			//自定义比较器
		Comparator<Map.Entry<Character, Integer>> descValue = new Comparator<Map.Entry<Character,Integer>>(){
			@Override
			public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {// o1和o2每次只取一个数据,就一次只比较两个数据
				int i1 = o1.getValue();	// 获取键的值(即字符对应出现的频率)
				int i2 = o2.getValue();	
				if (i1 != i2) { //若不同字符出现的频率不等,则返回1或-1
					return (i1 > i2) ? -1 : 1;//如果返回负值,那么i1和i2会倒序排序,返回正值,那么i1和i2会正序排序
				} 
				else {
					return 0;//返回0说明i1和i2相等
				}
			}
		};
		//取出map中的键和对应的值
		Set<Map.Entry<Character, Integer>> set = hm.entrySet();//通过entrySet()方法将map集合中的映射关系取出(这个关系就是Map.Entry类型)
		List<Map.Entry<Character, Integer>> list = new ArrayList<Map.Entry<Character, Integer>>(set);//创建一个List的对象,list这个链表中的元素是Map类型的元素
		Collections.sort(list, descValue);//根据比较器返回值对值(频率)排序
		//获得map的迭代器,用作遍历map中的每一个键值对
		Iterator<Map.Entry<Character, Integer>> iter = list.iterator();
		 System.out.print("\n本文中出现次数最高的前十个字: \n");
            for(int n=0;n<10;n++){ //取出迭代器中前十个键值对
                Map.Entry<Character, Integer> map = iter.next();//获得键值对
                char k = map.getKey();//获取map的键(对应文档中的字符)
                int v = map.getValue();//获取键对应的值(字符出现的频率)
                System.out.print("\n   "+k+" ——  "+v );
            }
        }		
        catch(IOException e){
            System.out.println("文件读取错误");
        }
        finally{
            try{
                if(buf!=null)
                    buf.close();//关闭数据流
            }
            catch(IOException e){
                System.out.println("文件关闭错误");
            }
			double end = System.currentTimeMillis(); // 程序结束时间,调用系统当前时间
        double time = end - begin;// 程序的运行时间
 
        System.out.println("\n程序用时:"+time/1000 + "秒");//输出执行完程序的用时,1ms=1/1000 s
        }
    }
}

结果演示:

【java】实现txt文档中汉字频率排序及输出频率最高的前十个汉字
程序用时:183.44秒