查询文件中每个单词出现的次数
一、使用单线程
分析:
1、后续会使用多线程来跑这个业务所以可以测试单线程和多线程所用的时间
这个可以在业务逻辑前获取当前时间戳,业务逻辑后获取时间戳,相减获取所用的时间。
2、使用map集合(单词为key 数量为value)
3、获取文件内容 (可以使用BufferReader 一行一行获取)
4、每行获取后使用split分割成数组
5、然后把数组遍历存入map中,每出现一次就+1
6、使用StringBuffer将需要的数据拼接,使用BufferWriter存入文件中
分析完成编写代码
public class WordCountSingle(){
public static void main(String[] args){
//获取业务前当前时间戳
long first = System.currentTimeMillis();
//定义Map集合,将单词存入key,数量存入value
Map<String,Integer> map = new HashMap<>();
//使用字符流获取文件内容
BufferReader br = null;
try {
// 获取到文件内容
br = new BufferedReader(new FileReader("E:/workcount.txt"));
bw = new BufferedWriter(new FileWriter("E:/singleCount.txt"));
String lineStr = "";
while ((lineStr = br.readLine()) != null) {
// 将没一行用空格分割
String[] split = lineStr.split(" ");
for (int i = 0; i < split.length; i++) {
// 如果map的key中包含遍历中的单词
if (map.containsKey(split[i])){
// 当时出现的次数 value+1
Integer integer = map.get(split[i])+1;
map.put(split[i],integer);
}else {
// map的key中没有包含遍历中的单词,则存入map
map.put(split[i],1);
}
}
}
// 定义StringBuffer去拼接结果
StringBuffer sb = new StringBuffer();
for (String key : map.keySet()) {
sb.append(key+"出现了"+map.get(key)+"次\n");
// System.out.println();
}
long last = System.currentTimeMillis()-first;
sb.append("一共用了"+last+"ms");
// 写入文件
bw.write(String.valueOf(sb));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
br.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
二、使用多线程
2.1线程
2.1.1 分析线程
每个线程的逻辑与单线程中的2、4、5这三条类似
2.1.2编写线程
import java.util.HashMap;
import java.util.Map;
/**
* 多线程分析:
* 每个线程与单线程一致
* 将map弄成类中的属性
*/
public class WordCount implements Runnable{
// 定义一个空字符串
String str = "";
// 定义一个map 将查出的结果存入map中
Map<String ,Integer> map = new HashMap<>();
// 构造函数把字符串传过来
public WordCount(String str) {
this.str = str;
}
@Override
public void run() {
String[] split = str.trim().split(" ");
for (int i = 0; i < split.length; i++) {
if (map.containsKey(split[i])){
Integer integer = map.get(split[i])+1;
map.put(split[i],integer);
}else {
map.put(split[i],1);
}
}
}
}
2.2 主线程
2.2.1 分析主线程业务逻辑
1、先进行单线程中获取运行时间的方法 (单线程中的 1)
2、创建线程池(后续创建的线程都由线程池管理)
3、把每个线程获取到的map放到Map<String , Map<String, Integer>>中
4、获取文件内容,将多行内容拼接到StringBuffer中
5、将这个字符串放入子线程去跑
6、获取完到子线程所处理完的map并处理
7、使用StringBuffer将需要的数据拼接,使用BufferWriter存入文件中
2.2.2 主线程业务逻辑编写
public class WordCountTest {
public static void main(String[] args) {
// 当前时间戳
long first = System.currentTimeMillis();
// 获取文件内容
BufferedReader br = null;
BufferedWriter bw = null;
// 创建线程池
ExecutorService executorService = Executors.newCachedThreadPool();
// 创建从线程中处理完的值的map
Map<String,Map<String,Integer>> map = new HashMap<>();
try {
br= new BufferedReader(new FileReader("E:/workcount.txt"));
bw = new BufferedWriter(new FileWriter("E:/moreCount.txt"));
// 读到了第几行
int line = 0;
String lineStr = "";
// 定义stringbuffer
StringBuffer sb = new StringBuffer();
while ((lineStr = br.readLine()) != null) {
line++;
sb.append(lineStr+" ");
// 每读100000行创建一个线程 在线程里去处理
if (line%100000==0){
WordCount wordCount = new WordCount(sb.toString());
// 把拼接后的字符串传入线程后,清空
sb.delete(0,sb.length());
Thread thread = new Thread(wordCount);
map.put("Thread-"+line/100000,wordCount.map);
// 每次线程放入线程池去处理
executorService.execute(thread);
}
}
// 后续可能还会有不到100000行数据需要处理,可以新建线程处理,也可以在main主线程中处理
WordCount wordCount = new WordCount(sb.toString());
Thread thread = new Thread(wordCount);
map.put("Thread-last",wordCount.map);
executorService.execute(thread);
// 线程池停止存放
executorService.shutdown();
// 创建需要写入文件的map
Map<String ,Integer> mapResult = new HashMap<>();
// 一直循环到所有线程结束
while (true) {
// 如果所有线程已结束
if (executorService.isTerminated()){
// 处理当前map获取需要的值
for (String haveKey : map.keySet()) {
for (String singleWord : map.get(haveKey).keySet()) {
if (mapResult.containsKey(singleWord)){
Integer integer = map.get(haveKey).get(singleWord)+mapResult.get(singleWord);
mapResult.put(singleWord,integer);
}else {
Integer integer = map.get(haveKey).get(singleWord);
mapResult.put(singleWord,integer);
}
}
}
break;
}
}
// 需要存入文件的数据
StringBuffer result = new StringBuffer();
for (String singleWord : mapResult.keySet()) {
result.append(singleWord+"出现了"+mapResult.get(singleWord)+"次\n");
}
// 一共用了多少毫秒
long last = System.currentTimeMillis() - first;
result.append("一共用了"+last+"ms");
bw.write(result.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}