Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

221801427 #84

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
82be2bb
commit test
raiLGun2000 Feb 21, 2021
65139d6
commit test 2
raiLGun2000 Feb 21, 2021
8014258
commit test 3
raiLGun2000 Feb 22, 2021
9f85000
Update codestyle.md
raiLGun2000 Feb 22, 2021
453cd69
Update codestyle.md
raiLGun2000 Feb 22, 2021
08744fd
建立了基本架构
raiLGun2000 Feb 25, 2021
96f0981
实现字符计算,以及对应的文件读写功能
raiLGun2000 Feb 25, 2021
93da9e6
重写了算法实现,增加计算行数功能
raiLGun2000 Feb 25, 2021
afca1e9
增加了计算有效单词总数的功能
raiLGun2000 Feb 26, 2021
bec7a36
增加了统计词频功能,输出功能也完整了
raiLGun2000 Feb 26, 2021
80cff79
修改了一些代码规范上的细节
raiLGun2000 Feb 27, 2021
0534b7f
改用StringBuilder提高性能
raiLGun2000 Feb 27, 2021
1a80df5
改进了部分算法效率
raiLGun2000 Feb 27, 2021
c5a071d
修改了读取算法与计算行数算法以适应读取\r的需要
raiLGun2000 Feb 28, 2021
f4d5396
输出格式,细节修改
raiLGun2000 Feb 28, 2021
150b6f2
提取了读取字符串并拆分为有效单词Map的方法,提高效率
raiLGun2000 Feb 28, 2021
eb4c651
读取文件的方式改用NIO以提升性能
raiLGun2000 Mar 4, 2021
b504f6a
优化了性能:采用StringTokenizer分割字符串,采用多线程;删去了不必要的导入。
raiLGun2000 Mar 4, 2021
8b4fec5
合并计算字符数与单词数的类,添加注释与README文本,更改编码模式为UTF-8解决提交时的乱码问题
raiLGun2000 Mar 5, 2021
acc92c0
Update README.md
raiLGun2000 Mar 5, 2021
aef476f
Delete input.txt
raiLGun2000 Mar 5, 2021
33e7a5e
Delete output.txt
raiLGun2000 Mar 5, 2021
8729a65
Update FilePrinter.java
raiLGun2000 Mar 5, 2021
7457ce1
采用了更高效的分析有效单词的方法
raiLGun2000 Mar 6, 2021
22ea04d
Merge branch 'main' of https://github.com/raiLGun2000/PersonalProject…
raiLGun2000 Mar 6, 2021
bfd5527
Update FileReader.java
raiLGun2000 Mar 6, 2021
697ac97
删除了作业截止后误操作提交的改动,程序已不包含截至之后commit的代码,望助教海涵。
raiLGun2000 Mar 7, 2021
4868c32
还原为截止前提交的代码
raiLGun2000 Mar 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions 221801427/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# PersonalProject-Java


----------


## 功能简介
输入英文文本(只考虑Ascii码,汉字不需考虑)
<br>1. 统计字符数(空格,水平制表符,换行符,均算字符)
<br>2. 统计有效行数(任何包含非空白字符的行,都需要统计)
<br>3. 统计单词数(至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写)
<br>4. 统计频率最高的10个单词的出现次数(值降序,键字典序)
<br> 按以上顺序逐行打印至输出文本,输出的格式如下

> characters: number <br>
words: number <br>
lines: number <br>
word1: number <br>
word2: number <br>
...


----------


## 运行方式
运行cmd

javac -encoding UTF-8 WordCount.java
java WordCount input.txt output.txt


----------


## 作业链接
[寒假作业(2/2) 作业要求](https://edu.cnblogs.com/campus/fzu/2021SpringSoftwareEngineeringPractice/homework/11740)


----------


## 博客链接
[我的博客](https://www.cnblogs.com/railgunSE/)


----------


## 签入记录
### 第一次commit
建立了基本架构,制定了代码规范
### 第二次commit
实现字符计算,以及对应的文件读写功能
### 第三次commit
重写了算法实现,增加计算行数功能
### 第四次commit
增加了计算有效单词总数的功能
### 第五次commit
增加了统计词频功能,输出功能也完整了
### 第六次commit
改用StringBuilder提高性能,修改、增加了一些代码规范上的细节
### 第七次commit
通过去删去不必要的字符操作,改进了部分算法效率
### 第八次commit
修改了读取算法与计算行数算法以适应读取\r的需要
### 第九次commit
输出格式,细节修改,所需功能基本完成完备
### 第十次commit
提取了读取字符串并拆分为有效单词Map的方法,提高效率
### 第十一次commit
改用NIO读取文件以提升性能
### 第十二次commit
优化了性能:采用StringTokenizer分割字符串,采用多线程<br>删去了之前尝试各类算法时遗留的不必要的导入
### 第十三次commit
合并计算字符数与单词数的类,添加注释与README文本<br>更改编码模式为UTF-8解决提交时的乱码问题




110 changes: 110 additions & 0 deletions 221801427/codestyle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
## 代码规范

- 缩进

>1、使用的缩进的字符数为4个空格,用Tab(定义Tab键扩展成为4个空格键)来进行缩进,Tab键在不同的情况下会显示不同的长度,严重干扰阅读体验。4个空格的距离从可读性来说,正好。

>2、在使用if或while等嵌套结构时,在if或while等语句下再进行Tab(扩展为4个空格)缩进,使程序看起来更清晰、美观。

- 变量命名

>1、局部变量使用lowerCamelCase风格,必须遵从驼峰形式。局部变量名采用英文单词的来命名,这样更能明白变量的含义。绝不使用拼音与英文混合的方式或直接使用中文的方式。
>>正例:studentId/teacherId
反例: DaZhePromotion [打折] / getPingfenByName() [评分] / int某变量 = 3

>2、遇到含义相同的变量,会在末尾用1,2来区别。但也有例外,在使用循环变量时,因无特殊含义,仅用i,j,k来定义。
>>正例:p1/p2/p3 和 for(i = 0;。。。)

>3、在标识符命名方面,少采用缩写,若采用缩写则查询国际通用的写法,用会发音的部分来命名,并在不容易理解的缩写命名后添加注释。标识符长度跟随所要表达的含义来增减长度,以使其更容易理解。在标识符命名中,最重要的是要保持一致性——在整个程序中,对变量或是函数一类使用相同的命名规则。
>>正例:int temp 和 int tmp

- 每行最多字符数

>1、每行行宽(含缩进)不允许超过100个字符。

>2、当一个程序行很长时,在适当位置运用回车键将程序分行,使其不破坏语句的完整性,也使语句看起来显得不混乱、零散。

- 函数最大行数

>1、一个函数允许包含语句的行数我限制为80行,不包括空行和注释。

>2、一个函数的最大长度和函数的复杂程度以及缩进大小成反比。

- 函数、类命名

>1、函数名使用lowerCamelCase风格,必须遵从驼峰形式。函数名用动词打头,以名词结尾的形式(少数会只有动词命名),使函数功能更容易理解。
>>正例:countWord/getId

>2、类名使用UpperCamelCase风格,必须遵从驼峰形式。
>>正例:WordCount/Lib

- 常量

>1、常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚。
>>正例:public static final int YEAR = 365;
>>正例: MAX_STOCK_COUNT
反例: MAX_COUNT

>2、如果变量值仅在一个范围内变化用Enum类。如果还带有名称之外的延伸属性,必须使用Enum类,类名后缀带Enum以清晰表示,枚举成员名称需要全大写,单词间用下划线隔开。下面正例中的数字就是延伸信息,表示星期几。
>>正例:publicEnum{MONDAY(1),TUESDAY(2),WEDNESDAY(3),
THURSDAY(4),FRIDAY(5),SATURDAY(6),SUNDAY(7);}

- 空行规则

>1、变量定义和方法实现间增加空行,便于阅读。

>2、在函数之间,增加空行来分割函数,这样使函数之间显得不拥挤,区分更加明显。

- 注释规则

>1、类、类方法的注释使用/*内容*/格式。

>2、一般在变量名后,添加一行注释。
>>正例:char option; //功能选项

>3、边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。

>4、注释尽量只用ASCII字符,不要用中文或其他特殊字符,利于程序的可移植性。

- 操作符前后空格

>1、一元运算符与变量之间没有空格
>>正例:i++/!flag

>2、二元运算符与变量之间必须有空格。
>>正例:int i = 0;/sum = x + y;

- 大括号位置

>1、每个“{”和“}”都独占一行。
>>正例:<br>if (condition)<br>
{<br>
&emsp;&emsp;DoSomething();<br>
}<br>
else<br>
{<br>
&emsp;&emsp;DoSomethingElse();<br>
}

>2、在if等语句块较为简单时,也不省略左右大括号的使用,以使程序显得更清晰、工整。

- 其他规则

>1、需要使用变量时,在使用前定义,避免一些需要用到其值时,无法获得的情况。例如:
>>正例:int i;
&emsp;&emsp;&emsp; for(i = 0;。。。)

>2、多个变量定义时分行写,使程序更加美观。
>>正例:x = 1;
&emsp;&emsp;&emsp;y = 2;
&emsp;&emsp;&emsp;z = 3;

>3、变量初始化时,提倡在尽可能小的作用域中声明变量,离第一次使用越近越好。这使得代码易于阅读,易于定位变量的声明位置、变量类型和初始值。
>>正例:int i = 3;

>4、多个不同的运算符同时存在时合理使用括号来明确优先级。
>>例:2 << 2 + 1 * 3 - 4
&emsp;&emsp;2 << (2 + 1 * 3 - 4)

>5、避免相同的代码段在多个地方出现相同的代码,必须归纳出来并且用一个类封装起来。
语句嵌套层次不得超过3层,超出的必须抽取出中间函数。
95 changes: 95 additions & 0 deletions 221801427/src/WordCount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import lib.service.*;
import lib.tool.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class WordCount
{
/**
* @param inputFileName
* @param outputFileName
*/
private static String inputFileName;
private static String outputFileName;

public WordCount(String inputFileName, String outputFileName)
{
WordCount.inputFileName = inputFileName;
WordCount.outputFileName = outputFileName;
}

public void Count()
{
final String content = FileReader.readFile(inputFileName);// 从文件读取字符串
final HashMap<String, Integer> words = StringAnalyser.analyseString(content);// 从字符串拆分有效单词,统计入HashMap

ExecutorService executor = Executors.newCachedThreadPool();

Future<Integer> charCnt = executor.submit(new Callable<Integer>()
{
// 统计字符数
public Integer call()
{
return CharAndWordCounter.countChar(content);
}
});

Future<Integer> lineCnt = executor.submit(new Callable<Integer>()
{
// 统计有效行数
public Integer call()
{
return LineCounter.countLine(content);
}
});

Future<Integer> wordCnt = executor.submit(new Callable<Integer>()
{
// 统计有效单词数
public Integer call()
{
return CharAndWordCounter.countWord(words);
}
});

Future<ArrayList<HashMap.Entry<String, Integer>>> freqList = executor
.submit(new Callable<ArrayList<HashMap.Entry<String, Integer>>>()
{
// 排序词频前10单词
public ArrayList<HashMap.Entry<String, Integer>> call()
{
return FrequencySorter.sortFrequency(words);
}
});

try
{
FilePrinter.writeFile(charCnt.get(), wordCnt.get(), lineCnt.get(), freqList.get(), outputFileName);// 打印结果
executor.shutdown();
}
catch (InterruptedException | ExecutionException e)
{
e.printStackTrace();
}
}

public static void main(String[] args)
{
WordCount cmd;

if (args.length != 2)
{
System.out.println("Invalid input");
return;
}
cmd = new WordCount(args[0], args[1]);// 传入参数(输入输出文件名)
// cmd = new WordCount("src/input.txt", "src/output.txt");
cmd.Count();// 统计
}
}
24 changes: 24 additions & 0 deletions 221801427/src/lib/service/CharAndWordCounter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package lib.service;

import java.util.HashMap;

public class CharAndWordCounter
{
/**
* @param content
* @return 字符总数
*/
public static int countChar(String content)
{
return content.length();// 直接返回字符串长度
}

/**
* @param words
* @return 单词总数
*/
public static int countWord(HashMap<String, Integer> words)
{
return words.size();// 返回HashMap规模表示有效单词总数
}
}
29 changes: 29 additions & 0 deletions 221801427/src/lib/service/FrequencySorter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package lib.service;

import java.util.*;
import java.util.stream.Collectors;

public class FrequencySorter
{
public static final int MAX_SIZE = 10;

/**
* @param words
* @return freqList
*/
public static ArrayList<HashMap.Entry<String, Integer>> sortFrequency(HashMap<String, Integer> words)
{
words = words.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue()// 值排序
.reversed()// 倒序为降序
.thenComparing(Map.Entry.comparingByKey()))// 键排序(字典序)
.limit(MAX_SIZE)// 前MAX_SIZE个
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldVal, newVal) -> oldVal, LinkedHashMap::new));// 返回map

ArrayList<HashMap.Entry<String, Integer>> freqList = new ArrayList<HashMap.Entry<String, Integer>>(
words.entrySet());

return freqList;
}
}
28 changes: 28 additions & 0 deletions 221801427/src/lib/service/LineCounter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package lib.service;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LineCounter
{
private static final String VALID_LINE_REGEX = "(^|\n)\\s*\\S+";
private static final Pattern VALID_LINE_PATTERN = Pattern.compile(VALID_LINE_REGEX);

/**
* @param content
* @return 有效行数
*/
public static int countLine(String content)
{
int cnt = 0;
Matcher matcher;

matcher = VALID_LINE_PATTERN.matcher(content);
while (matcher.find())
{
//利用正则表达式匹配有效行,空行不统计,包括\t \r \n 空格以及由他们组成的情况
cnt++;
}
return cnt;
}
}
Loading