JAVA实现统计文本中每个单词数量并画图打印

假设我们有一段英文文本,我们希望统计出其中每个单词数量,并且以此画出一幅统计图(使用JAVAFX实现),我们该怎么做?

注:只支持统计英文文本

最后的效果如下(表格太长,只展示部分):
在这里插入图片描述
完整的代码放在文章结尾,大家可以先复制看下效果。

对于这道题目,我将它分为三个部分:

1. 实现对文本的读写

java中对文本的阅读方式有很多,也有很多讲解,所以这里我不做过多的例举,这里直接展示我的读文本代码:

值得注意的是,这里我们将读下来的文本存放在字符串中,并且返回,等待处理。

// 读文件
	private static String readString3(String fileName)

	{

		String str = "";

		File file = new File(fileName);

		try {

			FileInputStream in = new FileInputStream(file);

			// size 为字串的长度 ,这里一次性读完

			int size = in.available();

			byte[] buffer = new byte[size];

			in.read(buffer);

			in.close();

			str = new String(buffer, "GB2312");

		} catch (IOException e) {

			// TODO Auto-generated catch block

			e.printStackTrace();
			return null;

		}

		return str;

	}

2. 在对文本进行处理后,实现单词个数的统计

对于这个部分,我们也应该有清晰的思路:

1. 我们的图表需要什么数据?又要这怎样存储这些数据?

很显然,对于一个柱状图,无非是一 一对应的横纵坐标,因此我们需要两个List,一个存储单词(不重复),一个存储单词的数量,两者的数据一一对应。
在这里插入图片描述
比如,对于上图,我们可以读出:我们又7个secure,20个a…

由此我们解决了第一个大问题,那么我们如何得到这两个List呢?

2. 我们如何得到这些数据?

要想统计每个单词的个数,首先要让字符串中只剩下英文字符,然后筛选掉重复的单词,因此,我总结了一下筛选步骤:

  1. 替换所有的符号到空格
  2. 将所有字符转化位小写
  3. 分割字符串
  4. 单词去重
  5. 去除数字的字符串
  6. 统计对应单词数量

这里还要插入小段内容,为了实现键盘输入文件名,我又加了一下段代码:

Scanner input = new Scanner(System.in);
		System.out.println("请输入Java源文件名");
		String fileName = input.next();
		
		
		File file = new File(fileName);
		if (!file.exists()) {
			System.out.println("节点基本信息文件未找到");
			System.exit(0);
		}
		//str1接受含文本内容的字符串
		String str1 = readString3(fileName);

接下来我们来详细说一下如何筛选:

1. 替换所有的符号到空格

这里的实现很简单,我们将所有待替换字符放在一个字符数组Eroor_str中,如果str1中的字符在Eroor_str中,我们就替换该字符位空格。

String Eroor_str = "~@#$%^&*()_-+=<>?/,.:;{}[]|\\'\"\"\"\r\n";

		for (int i = 0; i < Eroor_str.length(); i++) {
			str1 = str1.replace(Eroor_str.charAt(i), ' ');
		}
2. 将所有字符转化位小写

对于大小写的字母,计算机会识别为两个单词,所以我们得吧大小写统一,这里我们直接调用库函数 toLowerCase()

str1 = str1.toLowerCase();
3. 分割字符串

经过上面两步,我们要进行关键的一步。
我们认定一个单词的依据是 该字符串前后均为空格(暂不考虑该字符串的语义是否存在),所以我们对每个空格处进行切割,这样我就的到了所有的单个单词。

String[] arr = str1.split(" ");

split()函数可以将字符串分割为子字符串,我们只需要用一个字符串数组去接受即可。

4. 去重

接着我们将这个 字符串数组 强制转化 为一个List,并且新建一个List,命名为result,这个List我们用来存储不重复的所有单词

我们将list中的数据一个一个添加到result中,但是,在加入元素之前时,我们要判断该元素是否已经在result中存在,如果不存在,就加入,反之不加入。
这样,我们就实现了“去重

List<String> list = Arrays.asList(arr);

		List<String> result = new ArrayList<String>(list.size());
		for (String str : list) {
			if (!result.contains(str)) {
				result.add(str);
			}
		}
5. 去除数字的字符串

我们先不管list这个List,我们对result进行处理:
我们还需要将数字字符串和含字符的字符串筛选掉,下面的三句代码很简洁的达到效果,这里限于篇幅,不过多讲解。

Pattern pattern = Pattern.compile("\\d");// 匹配数字
Predicate<String> filter = s -> pattern.matcher(s).find();
result.removeIf(filter);

6. 统计对应单词的数量

这一步也是重要的一步,思考了很久,如何在不用哈希和正则表达式的情况下进行筛选。

我们现在有两个LIst:

  • list,存储了所有的单词
  • result,存储了所有去重后的单词

这样问题逻辑变得简单粗暴:我们将result的单词以此拿出来 与list中的单词逐个比较,相同就加一即可,最终将所有单词数目存在一个数组中。

int wordCounts[] = new int[result.size()];

		for (int i = 0; i < arr.length; i++) {

			System.out.print("/" + arr[i] + "/");
		}

		System.out.print("\n");
		System.out.print(list);
		System.out.print("\n");
		System.out.print(result);
		System.out.print("\n");

		for (int i = 0; i < result.size(); i++) {
			wordCounts[i] = 0;
			for (int j = 0; j < list.size(); j++) {
				if (list.get(j).equals(result.get(i))) {
					wordCounts[i] += 1;
				}
			}

		}

值得注意的是,我们在比较元素是否相等的时候,不能使用==,而是要使用
equal()方法去比较
。否则我们会得到所有的计数都为0.

原因在于,在JAVA中,String 不是一个基本的数据类型,而是一个引用数据类型,对于运算符==来说,它的运算规则如下:

== :运算符
1.可以使用基本运算类型和引用数据类型变量中
2.如果比较的是基本数据类型,比较两个变量保存的数据是否相等
如果比较的是引用数据类型:比较的是两个数据得到地址值是否相同

所以我们对两个String类型使用== ,比较的是地址,而不是数值。

所以我们要是用equal()函数进行内容比较,虽然equal的本质也是==。但系统对于 像String,Date,File,包装类等都重写了Object类中的equals()方法 ,重写之后,比较的不是两个引用的地址是否相同,而是比较两个对象的“实体内容”是否相同

最后我们想要同时返回result和wordCount.
显然不行,所以我稍作处理,将两者合并:

效果如下:
在这里插入图片描述

List list2 = new ArrayList<>();

		System.out.println("\n");
		for (int i = 0; i < result.size(); i++) {
			list2.add(result.get(i));
			list2.add((wordCounts[i]));
		}

		System.out.println(list2);

		return list2;

3. 使用JAVAFX进行绘图

对于Javafx,我不做过多的讲解,有很多教程。

public void start(Stage primaryStage) throws Exception {
       
		
	
		
		List list2 = new ArrayList<>();// 存數字
		List<String> list3 = new ArrayList<String>();// 存單詞
		List<String> list = TurnInto();// 存儲了所有單詞的list(不重複)
		for (int i = 3; i < list.size(); i = i + 2) {
			list2.add(list.get(i));
		}
		for (int i = 2; i < list.size(); i = i + 2) {
			list3.add(list.get(i));
		}

		// 定义坐标轴,X轴表示比较的类别,y轴表示出现次数
		// Defining the x axis
		CategoryAxis xAxis = new CategoryAxis();

		// xAxis.setCategories(FXCollections.<String>observableArrayList(list3));
		xAxis.setLabel("词");

		// Defining the y axis
		NumberAxis yAxis = new NumberAxis();
		yAxis.setLabel("出现次数");

		// 创建条形图
		// Creating the Bar chart
		
		BarChart<String, Number> barChart = new BarChart<>(xAxis, yAxis);
		barChart.setTitle("词频统计图");
	    //barChart.setMaxWidth(5000);
		barChart.setMinSize(10000, 50);
		
		
		for (int i = 0; i < list3.size(); i++) {
			XYChart.Series<String, Number> series1 = new XYChart.Series<>();
			series1.setName(list3.get(i));
			series1.getData().add(new XYChart.Data<>(list3.get(i), (int) list2.get(i)));
			barChart.getData().addAll(series1);
		}

		// 创建组对象
		Group root = new Group(barChart);
		// 创建场景对象
		Scene scene1 = new Scene(root, 10000, 300);
		// 设置舞台的标题
		primaryStage.setTitle("詞頻統計表");
		// 将场景添加到舞台
		primaryStage.setScene(scene1);
		// 显示舞台的内容
		primaryStage.show();
		// 启动应用程序

	}

完整代码

package WordCounts;

import java.util.Scanner;
import java.util.function.Predicate;
import java.util.regex.Pattern;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.stage.Stage;


import java.io.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javafx.scene.Group;
//javaFX图形化包
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

//abcd.txt
public class test2 extends Application {

	
	class CustomPane extends StackPane{//定义了StackPane的CustomPane类,
		public CustomPane(String title) {
			getChildren().add(new Label(title));//加入一个标签(标题)
			setStyle("-fx-border-color:red");//为边框颜色设置样式
			setPadding(new Insets(11.5,12.5,13.5,14.5));//设置内边距
		}
	}
	
	public void start(Stage primaryStage) throws Exception {
       
		
	
		
		List list2 = new ArrayList<>();// 存數字
		List<String> list3 = new ArrayList<String>();// 存單詞
		List<String> list = TurnInto();// 存儲了所有單詞的list(不重複)
		for (int i = 3; i < list.size(); i = i + 2) {
			list2.add(list.get(i));
		}
		for (int i = 2; i < list.size(); i = i + 2) {
			list3.add(list.get(i));
		}

		// 定义坐标轴,X轴表示比较的类别,y轴表示出现次数
		// Defining the x axis
		CategoryAxis xAxis = new CategoryAxis();

		// xAxis.setCategories(FXCollections.<String>observableArrayList(list3));
		xAxis.setLabel("词");

		// Defining the y axis
		NumberAxis yAxis = new NumberAxis();
		yAxis.setLabel("出现次数");

		// 创建条形图
		// Creating the Bar chart
		
		BarChart<String, Number> barChart = new BarChart<>(xAxis, yAxis);
		barChart.setTitle("词频统计图");
	    //barChart.setMaxWidth(5000);
		barChart.setMinSize(5000, 50);
		
		
		for (int i = 0; i < list3.size(); i++) {
			XYChart.Series<String, Number> series1 = new XYChart.Series<>();
			series1.setName(list3.get(i));
			series1.getData().add(new XYChart.Data<>(list3.get(i), (int) list2.get(i)));
			barChart.getData().addAll(series1);
		}

		// 创建组对象
		Group root = new Group(barChart);
		// 创建场景对象
		Scene scene1 = new Scene(root, 5000, 300);
		// 设置舞台的标题
		primaryStage.setTitle("詞頻統計表");
		// 将场景添加到舞台
		primaryStage.setScene(scene1);
		// 显示舞台的内容
		primaryStage.show();
		// 启动应用程序

	}

	// 读文件
	private static String readString3(String fileName)

	{

		String str = "";

		File file = new File(fileName);

		try {

			FileInputStream in = new FileInputStream(file);

			// size 为字串的长度 ,这里一次性读完

			int size = in.available();

			byte[] buffer = new byte[size];

			in.read(buffer);

			in.close();

			str = new String(buffer, "GB2312");

		} catch (IOException e) {

			// TODO Auto-generated catch block

			e.printStackTrace();
			return null;

		}

		return str;

	}

	static List<String> TurnInto() {
		Scanner input = new Scanner(System.in);
		System.out.println("请输入Java源文件名");
		String fileName = input.next();
		
		
		File file = new File(fileName);
		if (!file.exists()) {
			System.out.println("节点基本信息文件未找到");
			System.exit(0);
		}
		String str1 = readString3(fileName);

		// 替换所有符号到空格
		String Eroor_str = "~@#$%^&*()_-+=<>?/,.:;{}[]|\\'\"\"\"\r\n";

		for (int i = 0; i < Eroor_str.length(); i++) {
			str1 = str1.replace(Eroor_str.charAt(i), ' ');
		}

		// 将所有字符转化为小写
		str1 = str1.toLowerCase();

		// 分割字符串
		String[] arr = str1.split(" ");
		List<String> list = Arrays.asList(arr);

		List<String> result = new ArrayList<String>(list.size());
		for (String str : list) {
			if (!result.contains(str)) {
				result.add(str);
			}
		}
		// 去除帶數字的字符串
		Pattern pattern = Pattern.compile("\\d");// 匹配数字
		Predicate<String> filter = s -> pattern.matcher(s).find();
		result.removeIf(filter);

		// 存儲每個字符串的個數的數組
		int wordCounts[] = new int[result.size()];

		for (int i = 0; i < arr.length; i++) {

			System.out.print("/" + arr[i] + "/");
		}

		System.out.print("\n");
		System.out.print(list);
		System.out.print("\n");
		System.out.print(result);
		System.out.print("\n");

		for (int i = 0; i < result.size(); i++) {
			wordCounts[i] = 0;
			for (int j = 0; j < list.size(); j++) {
				if (list.get(j).equals(result.get(i))) {
					wordCounts[i] += 1;
				}
			}

		}

		for (int i = 0; i < result.size(); i++) {
			System.out.print(wordCounts[i] + " ");
		}

		List list2 = new ArrayList<>();

		System.out.println("\n");
		for (int i = 0; i < result.size(); i++) {
			list2.add(result.get(i));
			list2.add((wordCounts[i]));
		}

		System.out.println(list2);

		return list2;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// List<String> list = TurnInto();
				Application.launch(args); // 启动这个程序 APPlication的方法
				//Application.launch(ScannerInterface.class);
	}


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ornamrr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值