描述:我们在大数据学习的起初,会写到WordCount这样的程序,对文档内单词的重复次数进行统计。
文档内容:
hadoop hive
hive spark
flume flink
hbase hive
hadoop spark flink
我们使用java代码实现这一功能,代码如下:
public class WordCountJava {
public static void main(String[] args) {
//第一步 连接HDFS集群
Configuration conf = new Configuration();
FileSystem fs = null;
try {
fs = FileSystem.get(new URI("hdfs://192.168.10.3:9000"), conf, "root");
/*
* 第二步 读取文件数据---IO流实现
* 四个抽象父类
* 字节流:InputStream OutputStream
* 字符流:Reader Writer
* */
//创建我们单词计数文件的输入流
FSDataInputStream open = fs.open(new Path("/wordcount.txt"));
//字节转字符流
InputStreamReader isr = new InputStreamReader(open);
BufferedReader br = new BufferedReader(isr);
String line;
//准备一个map集合 存放数据 数据格式 单词,单词出现的次数
Map<String,Integer> map = new HashMap<>();
//通过bufferedreader字符缓冲流的readLine方法 一次读取一行数据
//讲每一行数据按空格分割 统计次数
/**
* (line = br.readLine()) != null
* 之所以使用这个判断的原因是因为readLine方法的一个特性:
* readLine是用来判断你当前行有没有数据 如果有数据的话 那么讲这一行的数据赋值给一个Sring类型的一个变量
* 然后讲指针下移 当再调用一次readline方法的时候 那么返回的就不是当前行的数据了 而是下一行的数据
*/
while ((line = br.readLine()) != null){
// while ((br.readLine()) != null){
// String line = br.readLine();
System.out.println(line);
String[] words = line.split(" ");
/**
* 如果单词还没有在map集合添加 那么在map集合加入 word 1
* 如果出现的话 那么在map集合添加 word ,以前出现的次数+1
*/
for (String word:words){
if (map.get(word) == null){
map.put(word,1);
}else{
map.put(word,map.get(word)+1);
}
}
}
System.out.println(map);
} catch (Exception e) {
e.printStackTrace();
}finally {
if (fs != null){
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
其中,我们为什么使用这样的方法:
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
而不是使用:
while ((br.readLine()) != null){
String line = br.readLine();
System.out.println(line);
}
原因:
我们先将第二种方法的结果输出:
hive spark
hbase hive
null
java.lang.NullPointerException
显然第二种方式读取到的是文档的第2、4、6行
之所以使用line = br.readLine()) != null方法是因为readLine()方法的一个特性:
readLine()是用来判断当前行有没有数据,如果有数据的话将这一行数据赋值给一个String类型的变量,然后将指针下移,当在调用一次readLine()方法时,那么返回的就不是当前行的数据了,而是下一行的数据。
最后,给大家将一下使用java实现单词计数会出现的问题:
1、我们操作的数据是HDFS分布式集群,可能这个文件有好几个G的大小,如果使用Java那么我们必须把数据全部拉取到jvm内存中运行,可能会导致java内存直接崩溃。
2、如果我们不把数据全部拉取过来操作,那么可能会把java程序运行在不同的电脑上执行,只需要处理当前这个机器上的block块的数据就好了。
这样也会出现问题:Java代码分布式的运行在不同电脑上,那么处理结束之后怎么把结果汇总?怎么把控每个节点上程序有没有运行结束?
这样!!!我们就引入了MapReaduce框架技术!请看下期介绍!