本文通过仅使用HDFS的原生Java-API,不调用MapReduce,对文本单词进行词频统计。输入和输出文件位置均存放在HDFS上。
本程序使用到了properties配置文件指定连接配置、输入输出地址以及类名等。注意,当把类名写入配置文件并使用时,不能用new,而需要使用Java中的反射来获取类。
首先需要创建一个普通的maven项目,然后引入Hadoop和Junit的maven依赖。Junit主要用于单元测试(本来只有main程序可以运行的,导入Junit之后可以在任意函数前加@Test之后便可直接运行该程序),因此Junit可以根据具体需要和偏好决定是否导入。
maven依赖添加于pom.xml之中,具体配置如下:
<dependencies>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-clientartifactId>
<version>2.7.2version>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-hdfsartifactId>
<version>2.7.2version>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-commonartifactId>
<version>2.7.2version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.junit.jupitergroupId>
<artifactId>junit-jupiter-apiartifactId>
<version>RELEASEversion>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>compilescope>
dependency>
dependencies>
ADDRESS=hdfs://centos01:9000
USER=hadoop
INPUT_FILE=/test/HDFS/inputWords.txt
OUTPUT_FILE=/test/HDFS/realOut.txt
CONTEXT_CLASS=wordCount.Context
将该配置文件放在resources目录下。
本项目的大致逻辑和实现步骤是:
1)从properties文件中读入参数,如用户名、hdfs连接地址和端口号等,进行连接并获取FileSystem;
public class myConnection {
public static FileSystem fileSystem(Properties properties) throws URISyntaxException, IOException, InterruptedException {
URI address=new URI(properties.getProperty(Constants.ADDRESS.getValue()));
String user=properties.getProperty(Constants.USER.getValue());
Configuration conf=new Configuration();
FileSystem System=FileSystem.get(address,conf,user);
return System;
}
}
2)新建Context类,用于将原数据存入TreeMap(不使用HashMap的原因是HashMap本身是无序的,想要在输出时排好顺序),该类还包含分割和词频统计方法;
public class Context {
private TreeMap<String,Integer> map=new TreeMap<String,Integer>();
public void write(String vocabulary,int num)
{
vocabulary=vocabulary.toLowerCase();
if(map.containsKey(vocabulary))
shuffle(vocabulary);
else
map.put(vocabulary,num);
}
public void write(String vocabulary)
{
if(map.containsKey(vocabulary))
shuffle(vocabulary);
else
map.put(vocabulary,1);
}
public void shuffle(String key)
{
map.put(key,map.get(key)+1);
}
public TreeMap<String,Integer> read()
{
return map;
}
}
3)使用Context类,将从HDFS上读取的源数据进行分割和词频统计操作并存入Context.java中的TreeMap中。
public class Reader {
public static Context read(Properties properties,FileSystem fileSystem) throws URISyntaxException, IOException, InterruptedException, ClassNotFoundException, IllegalAccessException, InstantiationException {
Path path=new Path(properties.getProperty(Constants.INPUT_FILE.getValue()));
FSDataInputStream in = fileSystem.open(path);
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
String line="";
String contextClassName=properties.getProperty(Constants.CONTEXT_CLASS.getValue());
Class clazz=Class.forName(contextClassName);
Context context= (Context) clazz.newInstance();
while((line=reader.readLine())!=null)
{
//System.out.println(line);
String[] S=line.split(" ");
for(String s:S)
{
System.out.println(s);
context.write(s,1);
}
}
reader.close();
return context;
}
}
4)将结果输出到properties中的指定HDFS路径。
public static boolean output(Properties properties,FileSystem fileSystem,Context context) throws IOException {
TreeMap<String,Integer> myMap=context.read();
Iterator<Map.Entry<String, Integer>> it=myMap.entrySet().iterator();
FSDataOutputStream out = null;
Path outputPath=new Path(properties.getProperty(Constants.OUTPUT_FILE.getValue()));
if(fileSystem.exists(outputPath))
fileSystem.delete(outputPath);
out = fileSystem.create(outputPath);
while (it.hasNext())
{
java.util.Map.Entry<String,Integer> entry=it.next();
out.write((entry.getKey()+"\t"+entry.getValue()+"\n").getBytes());
}
out.flush();
out.close();
fileSystem.close();
return true;//若成功返回true
}
以上就是本文要讲的内容,本文通过仅使用HDFS的原生Java-API,不调用MapReduce,对来自HDFS文本单词进行词频统计操作,并上传到HDFS上。
最后附上本项目的github地址,供大家参考。github项目地址
第一次写博客,如有不足之处还请大家多多指教、多多包涵。如果觉得我写得不错,也可以点赞或者关注我,我也会定期更新更多的理论及实践的博客。
另,我之前也写过一篇同系列的关于MapReduce的实战文章以及关于Hive的原理介绍文章,也可供大家参考。
附上链接:
利用MapReduce实现账单统计
Hive学习笔记(1)——Hive原理初探