7521,WARD,SALESMAN,7698,22-2 月 -81,1250,500, ,JONES,MANAGER,7839,02-4 月 -81,2975,, ,MARTIN,SALESMAN,7698,28-9 月 -81,1250,1400, ,BLAK

Size: px
Start display at page:

Download "7521,WARD,SALESMAN,7698,22-2 月 -81,1250,500, ,JONES,MANAGER,7839,02-4 月 -81,2975,, ,MARTIN,SALESMAN,7698,28-9 月 -81,1250,1400, ,BLAK"

Transcription

1 MapReduce 应用案例 本文版权归作者和博客园共有, 欢迎转载, 但未经作者同意必须保留此段声明, 且在文章页面明显位置给出原文连接, 博主为石山园, 博客地址为 该系列课程是应邀实验楼整理编写的, 这里需要赞一下实验楼提供了学习的新方式, 可以边看博客边上机实验, 课程地址为 注 该系列所使用到安装包 测试数据和代码均可在百度网盘下载, 具体地址为 下载该 PDF 文件 1 环境说明 部署节点操作系统为 CentOS, 防火墙和 SElinux 禁用, 创建了一个 shiyanlou 用户并在系统根目录下创建 /app 目录, 用于存放 Hadoop 等组件运行包 因为该目录用于安装 hadoop 等组件程序, 用户对 shiyanlou 必须赋予 rwx 权限 ( 一般做法是 root 用户在根目录下创建 /app 目录, 并修改该目录拥有者为 shiyanlou(chown R shiyanlou:shiyanlou /app) Hadoop 搭建环境 : 虚拟机操作系统 : CentOS 位, 单核,1G 内存 JDK:1.7.0_55 64 位 Hadoop: 准备测试数据 测试数据包括两个文件 dept( 部门 ) 和 emp( 员工 ), 其中各字段用逗号分隔 : dept 文件内容 : 10,ACCOUNTING,NEW YORK 20,RESEARCH,DALLAS 30,SALES,CHICAGO 40,OPERATIONS,BOSTON emp 文件内容 : 7369,SMITH,CLERK,7902,17-12 月 -80,800,, ,ALLEN,SALESMAN,7698,20-2 月 -81,1600,300,30 第 1 页共 57 页

2 7521,WARD,SALESMAN,7698,22-2 月 -81,1250,500, ,JONES,MANAGER,7839,02-4 月 -81,2975,, ,MARTIN,SALESMAN,7698,28-9 月 -81,1250,1400, ,BLAKE,MANAGER,7839,01-5 月 -81,2850,, ,CLARK,MANAGER,7839,09-6 月 -81,2450,, ,KING,PRESIDENT,,17-11 月 -81,5000,, ,TURNER,SALESMAN,7698,08-9 月 -81,1500,0, ,JAMES,CLERK,7698,03-12 月 -81,950,, ,FORD,ANALYST,7566,03-12 月 -81,3000,, ,MILLER,CLERK,7782,23-1 月 -82,1300,,10 在 /home/shiyanlou/install-pack/class6 目录可以找到这两个文件, 把这两个文件上传到 HDFS 中 /class6/input 目录中, 执行如下命令 : cd /home/shiyanlou/install-pack/class6 hadoop fs -mkdir -p /class6/input hadoop fs -copyfromlocal dept /class6/input hadoop fs -copyfromlocal emp /class6/input hadoop fs -ls /class6/input 第 2 页共 57 页

3 3 应用案例 3.1 测试例子 1: 求各个部门的总工资 问题分析 MapReduce 中的 join 分为好几种, 比如有最常见的 reduce side join map side join 和 semi join 等 reduce join 在 shuffle 阶段要进行大量的数据传输, 会造成大量的网络 IO 效率低下, 而 map side join 在处理多个小表关联大表时非常有用 Map side join 是针对以下场景进行的优化 : 两个待连接表中, 有一个表非常大, 而另一个表非常小, 以至于小表可以直接存放到内存中 这样我们可以将小表复制多份, 让每个 map task 内存中存在一份 ( 比如存放到 hash table 中 ), 然后只扫描大表 : 对于大表中的每一条记录 key/value, 在 hash table 中查找是否有相同的 key 的记录, 如果有, 则连接后输出即可 为了支持文件的复制,Hadoop 提供了一个类 DistributedCache, 使用该类的方法如下 : (1) 用户使用静态方法 DistributedCache.addCacheFile() 指定要复制的文件, 它的参数是文件的 URI ( 如果是 HDFS 上的文件, 可以这样 : hdfs://jobtracker:50030/home/xxx/file) JobTracker 在作业启动之前会获取这个 URI 列表, 并将相应的文件拷贝到各个 TaskTracker 的本地磁盘上 (2) 用户使用 DistributedCache.getLocalCacheFiles() 方法获取文件目录, 并使用标准的文件读写 API 读取相应的文件 在下面代码中, 将会把数据量小的表 ( 部门 dept) 缓存在内存中, 在 Mapper 阶段对员工部门编号映射成部门名称, 该名称作为 key 输出到 Reduce 中, 在 Reduce 中计算按照部门计算各个部门的总工资 第 3 页共 57 页

4 3.1.2 处理流程图 测试代码 Q1SumDeptSalary.java 代码 (vi 编辑代码是不能存在中文 ): import java.io.bufferedreader; import java.io.filereader; import java.io.ioexception; import java.util.hashmap; import java.util.map; import org.apache.hadoop.conf.configuration; import org.apache.hadoop.conf.configured; import org.apache.hadoop.filecache.distributedcache; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.longwritable; import org.apache.hadoop.io.text; import org.apache.hadoop.mapreduce.job; import org.apache.hadoop.mapreduce.mapper; import org.apache.hadoop.mapreduce.reducer; import org.apache.hadoop.mapreduce.lib.input.fileinputformat; import org.apache.hadoop.mapreduce.lib.input.textinputformat; import org.apache.hadoop.mapreduce.lib.output.fileoutputformat; import org.apache.hadoop.mapreduce.lib.output.textoutputformat; import org.apache.hadoop.util.genericoptionsparser; import org.apache.hadoop.util.tool; import org.apache.hadoop.util.toolrunner; 第 4 页共 57 页

5 public class Q1SumDeptSalary extends Configured implements Tool { public static class MapClass extends Mapper<LongWritable, Text, Text, Text> { // 用于缓存 dept 文件中的数据 private Map<String, String> deptmap = new HashMap<String, String>(); private String[] kv; // 此方法会在 Map protected void setup(context context) throws IOException, InterruptedException { BufferedReader in = null; try { // 从当前作业中获取要缓存的文件 Path[] paths = DistributedCache.getLocalCacheFiles(context.getConfiguration()); String deptidname = null; for (Path path : paths) { // 对部门文件字段进行拆分并缓存到 deptmap 中 if (path.tostring().contains("dept")) { in = new BufferedReader(new FileReader(path.toString())); while (null!= (deptidname = in.readline())) { // 对部门文件字段进行拆分并缓存到 deptmap 中 // 其中 Map 中 key 为部门编号,value 为所在部门名称 deptmap.put(deptidname.split(",")[0], deptidname.split(",")[1]); catch (IOException e) { e.printstacktrace(); finally { try { if (in!= null) { in.close(); catch (IOException e) { e.printstacktrace(); public void map(longwritable key, Text value, Context context) throws IOException, InterruptedException { // 对员工文件字段进行拆分 第 5 页共 57 页

6 kv = value.tostring().split(","); // map join: 在 map 阶段过滤掉不需要的数据, 输出 key 为部门名称和 value 为员工工资 if (deptmap.containskey(kv[7])) { if (null!= kv[5] &&!"".equals(kv[5].tostring())) { context.write(new Text(deptMap.get(kv[7].trim())), new Text(kv[5].trim())); public static class Reduce extends Reducer<Text, Text, Text, LongWritable> { public void reduce(text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { // 对同一部门的员工工资进行求和 long sumsalary = 0; for (Text val : values) { sumsalary += Long.parseLong(val.toString()); // 输出 key 为部门名称和 value 为该部门员工工资总和 context.write(key, new public int run(string[] args) throws Exception { // 实例化作业对象, 设置作业名称 Mapper 和 Reduce 类 Job job = new Job(getConf(), "Q1SumDeptSalary"); job.setjobname("q1sumdeptsalary"); job.setjarbyclass(q1sumdeptsalary.class); job.setmapperclass(mapclass.class); job.setreducerclass(reduce.class); // 设置输入格式类 job.setinputformatclass(textinputformat.class); // 设置输出格式 job.setoutputformatclass(textoutputformat.class); job.setoutputkeyclass(text.class); job.setoutputvalueclass(text.class); // 第 1 个参数为缓存的部门数据路径 第 2 个参数为员工数据路径和第 3 个参数为输出路径 第 6 页共 57 页

7 String[] otherargs = new GenericOptionsParser(job.getConfiguration(), args).getremainingargs(); DistributedCache.addCacheFile(new Path(otherArgs[0]).toUri(), job.getconfiguration()); FileInputFormat.addInputPath(job, new Path(otherArgs[1])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[2])); job.waitforcompletion(true); return job.issuccessful()? 0 : 1; /** * 主方法, 执行入口 args 输入参数 */ public static void main(string[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new Q1SumDeptSalary(), args); System.exit(res); 编译并打包代码 进入 /app/hadoop-1.1.2/myclass/class6 目录中新建 Q1SumDeptSalary.java 程序代码 ( 代码页可以使用 /home/shiyanlou/install-pack/class6/q1sumdeptsalary.java 文件 ) cd /app/hadoop-1.1.2/myclass/class6 vi Q1SumDeptSalary.java 编译代码 javac -classpath../../hadoop-core jar:../../lib/commons-cli-1.2.jar Q1SumDeptSalary.java 把编译好的代码打成 jar 包 ( 如果不打成 jar 形式运行会提示 class 无法找到的错误 ) jar cvf./q1sumdeptsalary.jar./q1sumdept*.class mv *.jar../.. rm Q1SumDept*.class 第 7 页共 57 页

8 3.1.5 运行并查看结果 运行 Q1SumDeptSalary 时需要输入部门数据路径 员工数据路径和输出路径三个参数, 需要注意的是 hdfs 的路径参数路径需要全路径, 否则运行会报错 : 部门数据路径 :hdfs://hadoop:9000/class6/input/dept, 部门数据将缓存在各运行任务的节点内容中, 可以提供处理的效率 员工数据路径 :hdfs://hadoop:9000/class6/input/emp 输出路径 :hdfs://hadoop:9000/class6/out1 运行如下命令 : cd /app/hadoop hadoop jar Q1SumDeptSalary.jar Q1SumDeptSalary hdfs://hadoop:9000/class6/input/dept hdfs://hadoop:9000/class6/input/emp hdfs://hadoop:9000/class6/out1 运行成功后, 刷新 CentOS HDFS 中的输出路径 /class6/out1 目录, 打开 part-r 文件 第 8 页共 57 页

9 hadoop fs -ls /class6/out1 hadoop fs -cat /class6/out1/part-r 可以看到运行结果 : ACCOUNTING 8750 RESEARCH 6775 SALES 测试例子 2: 求各个部门的人数和平均工资 问题分析 求各个部门的人数和平均工资, 需要得到各部门工资总数和部门人数, 通过两者相除获取各部门平均工资 首先和问题 1 类似在 Mapper 的 Setup 阶段缓存部门数据, 然后在 Mapper 阶段抽取出部门编号和员工工资, 利用缓存部门数据把部门编号对应为部门名称, 接着在 Shuffle 阶段把传过来的数据处理为部门名称对应该部门所有员工工资的列表, 最后在 Reduce 中按照部门归组, 遍历部门所有员工, 求出总数和员工数, 输出部门名称和平均工资 处理流程图 第 9 页共 57 页

10 3.2.3 编写代码 Q2DeptNumberAveSalary.java 代码 : import java.io.bufferedreader; import java.io.filereader; import java.io.ioexception; import java.util.hashmap; import java.util.map; import org.apache.hadoop.conf.configuration; import org.apache.hadoop.conf.configured; import org.apache.hadoop.filecache.distributedcache; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.longwritable; import org.apache.hadoop.io.text; import org.apache.hadoop.mapreduce.job; import org.apache.hadoop.mapreduce.mapper; import org.apache.hadoop.mapreduce.reducer; import org.apache.hadoop.mapreduce.lib.input.fileinputformat; import org.apache.hadoop.mapreduce.lib.input.textinputformat; import org.apache.hadoop.mapreduce.lib.output.fileoutputformat; import org.apache.hadoop.mapreduce.lib.output.textoutputformat; import org.apache.hadoop.util.genericoptionsparser; import org.apache.hadoop.util.tool; import org.apache.hadoop.util.toolrunner; public class Q2DeptNumberAveSalary extends Configured implements Tool { public static class MapClass extends Mapper<LongWritable, Text, Text, Text> { // 用于缓存 dept 文件中的数据 private Map<String, String> deptmap = new HashMap<String, String>(); private String[] kv; // 此方法会在 Map protected void setup(context context) throws IOException, InterruptedException { BufferedReader in = null; try { // 从当前作业中获取要缓存的文件 Path[] paths = DistributedCache.getLocalCacheFiles(context.getConfiguration()); String deptidname = null; for (Path path : paths) { // 对部门文件字段进行拆分并缓存到 deptmap 中 if (path.tostring().contains("dept")) { 第 10 页共 57 页

11 in = new BufferedReader(new FileReader(path.toString())); while (null!= (deptidname = in.readline())) { // 对部门文件字段进行拆分并缓存到 deptmap 中 // 其中 Map 中 key 为部门编号,value 为所在部门名称 deptmap.put(deptidname.split(",")[0], deptidname.split(",")[1]); catch (IOException e) { e.printstacktrace(); finally { try { if (in!= null) { in.close(); catch (IOException e) { e.printstacktrace(); public void map(longwritable key, Text value, Context context) throws IOException, InterruptedException { // 对员工文件字段进行拆分 kv = value.tostring().split(","); // map join: 在 map 阶段过滤掉不需要的数据, 输出 key 为部门名称和 value 为员工工资 if (deptmap.containskey(kv[7])) { if (null!= kv[5] &&!"".equals(kv[5].tostring())) { context.write(new Text(deptMap.get(kv[7].trim())), new Text(kv[5].trim())); public static class Reduce extends Reducer<Text, Text, Text, Text> { public void reduce(text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { long sumsalary = 0; int deptnumber = 0; // 对同一部门的员工工资进行求和 for (Text val : values) { 第 11 页共 57 页

12 sumsalary += Long.parseLong(val.toString()); deptnumber++; // 输出 key 为部门名称和 value 为该部门员工工资平均值 context.write(key, new Text("Dept Number:" + deptnumber + ", Ave Salary:" + sumsalary / public int run(string[] args) throws Exception { // 实例化作业对象, 设置作业名称 Mapper 和 Reduce 类 Job job = new Job(getConf(), "Q2DeptNumberAveSalary"); job.setjobname("q2deptnumberavesalary"); job.setjarbyclass(q2deptnumberavesalary.class); job.setmapperclass(mapclass.class); job.setreducerclass(reduce.class); // 设置输入格式类 job.setinputformatclass(textinputformat.class); // 设置输出格式类 job.setoutputformatclass(textoutputformat.class); job.setoutputkeyclass(text.class); job.setoutputvalueclass(text.class); // 第 1 个参数为缓存的部门数据路径 第 2 个参数为员工数据路径和第 3 个参数为输出路径 String[] otherargs = new GenericOptionsParser(job.getConfiguration(), args).getremainingargs(); DistributedCache.addCacheFile(new Path(otherArgs[0]).toUri(), job.getconfiguration()); FileInputFormat.addInputPath(job, new Path(otherArgs[1])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[2])); job.waitforcompletion(true); return job.issuccessful()? 0 : 1; /** * 主方法, 执行入口 args 输入参数 */ public static void main(string[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new Q2DeptNumberAveSalary(), args); System.exit(res); 第 12 页共 57 页

13 3.2.4 编译并打包代码 进入 /app/hadoop-1.1.2/myclass/class6 目录中新建 Q2DeptNumberAveSalary.java 程序代码 ( 代码页可以使用 /home/shiyanlou/install-pack/class6/q2deptnumberavesalary.java 文件 ) cd /app/hadoop-1.1.2/myclass/class6 vi Q2DeptNumberAveSalary.java 编译代码 javac -classpath../../hadoop-core jar:../../lib/commons-cli-1.2.jar Q2DeptNumberAveSalary.java 把编译好的代码打成 jar 包, 如果不打成 jar 形式运行会提示 class 无法找到的错误 jar cvf./q2deptnumberavesalary.jar./q2deptnum*.class mv *.jar../.. rm Q2DeptNum*.class 运行并查看结果 运行 Q2DeptNumberAveSalary 时需要输入部门数据路径 员工数据路径和输出路径三个参数, 需要注意的是 hdfs 的路径参数路径需要全路径, 否则运行会报错 : 部门数据路径 :hdfs://hadoop:9000/class6/input/dept, 部门数据将缓存在各运行任务的节点内容中, 可以提供处理的效率 员工数据路径 :hdfs://hadoop:9000/class6/input/emp 输出路径 :hdfs://hadoop:9000/class6/out2 第 13 页共 57 页

14 运行如下命令 : cd /app/hadoop hadoop jar Q2DeptNumberAveSalary.jar Q2DeptNumberAveSalary hdfs://hadoop:9000/class6/input/dept hdfs://hadoop:9000/class6/input/emp hdfs://hadoop:9000/class6/out2 运行成功后, 刷新 CentOS HDFS 中的输出路径 /class6/out2 目录 hadoop fs -ls /class6/out2 hadoop fs -cat /class6/out2/part-r 打开 part-r 文件, 可以看到运行结果 : ACCOUNTING Dept Number:3,Ave Salary:2916 RESEARCH Dept Number:3,Ave Salary:2258 SALES Dept Number:6,Ave Salary: 测试例子 3: 求每个部门最早进入公司的员工姓名 问题分析 求每个部门最早进入公司员工姓名, 需要得到各部门所有员工的进入公司日期, 通过比较获取最早进入公司员工姓名 首先和问题 1 类似在 Mapper 的 Setup 阶段缓存部门数据, 然后 Mapper 阶段抽取出 key 为部门名称 ( 利用缓存部门数据把部门编号对应为部门名称 ),value 为员工姓名和进入公司日期, 接着在 Shuffle 阶段把传过来的数据处理为部门名称对应该部门所有员工 + 进入公司日期的列表, 最后在 Reduce 中按照部门归组, 遍历部门所有员工, 找出最早进入公司的员工并输出 第 14 页共 57 页

15 3.3.2 处理流程图 编写代码 import java.io.bufferedreader; import java.io.filereader; import java.io.ioexception; import java.text.dateformat; import java.text.parseexception; import java.text.simpledateformat; import java.util.date; import java.util.hashmap; import java.util.map; import org.apache.hadoop.conf.configuration; import org.apache.hadoop.conf.configured; import org.apache.hadoop.filecache.distributedcache; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.longwritable; import org.apache.hadoop.io.text; import org.apache.hadoop.mapreduce.job; import org.apache.hadoop.mapreduce.mapper; import org.apache.hadoop.mapreduce.reducer; import org.apache.hadoop.mapreduce.lib.input.fileinputformat; import org.apache.hadoop.mapreduce.lib.input.textinputformat; import org.apache.hadoop.mapreduce.lib.output.fileoutputformat; import org.apache.hadoop.mapreduce.lib.output.textoutputformat; 第 15 页共 57 页

16 import org.apache.hadoop.util.genericoptionsparser; import org.apache.hadoop.util.tool; import org.apache.hadoop.util.toolrunner; public class Q3DeptEarliestEmp extends Configured implements Tool { public static class MapClass extends Mapper<LongWritable, Text, Text, Text> { // 用于缓存 dept 文件中的数据 private Map<String, String> deptmap = new HashMap<String, String>(); private String[] kv; // 此方法会在 Map protected void setup(context context) throws IOException, InterruptedException { BufferedReader in = null; try { // 从当前作业中获取要缓存的文件 Path[] paths = DistributedCache.getLocalCacheFiles(context.getConfiguration()); String deptidname = null; for (Path path : paths) { if (path.tostring().contains("dept")) { in = new BufferedReader(new FileReader(path.toString())); while (null!= (deptidname = in.readline())) { // 对部门文件字段进行拆分并缓存到 deptmap 中 // 其中 Map 中 key 为部门编号,value 为所在部门名称 deptmap.put(deptidname.split(",")[0], deptidname.split(",")[1]); catch (IOException e) { e.printstacktrace(); finally { try { if (in!= null) { in.close(); catch (IOException e) { e.printstacktrace(); public void map(longwritable key, Text value, Context context) throws IOException, InterruptedException { 第 16 页共 57 页

17 // 对员工文件字段进行拆分 kv = value.tostring().split(","); // map join: 在 map 阶段过滤掉不需要的数据 // 输出 key 为部门名称和 value 为员工姓名 +","+ 员工进入公司日期 if (deptmap.containskey(kv[7])) { if (null!= kv[4] &&!"".equals(kv[4].tostring())) { context.write(new Text(deptMap.get(kv[7].trim())), new Text(kv[1].trim() + "," + kv[4].trim())); public static class Reduce extends Reducer<Text, Text, Text, Text> { public void reduce(text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { // 员工姓名和进入公司日期 String empname = null; String empenterdate = null; // 设置日期转换格式和最早进入公司的员工 日期 DateFormat df = new SimpleDateFormat("dd-MM 月 -yy"); Date earliestdate = new Date(); String earliestemp = null; // 遍历该部门下所有员工, 得到最早进入公司的员工信息 for (Text val : values) { empname = val.tostring().split(",")[0]; empenterdate = val.tostring().split(",")[1].tostring().trim(); try { System.out.println(df.parse(empEnterDate)); if (df.parse(empenterdate).compareto(earliestdate) < 0) { earliestdate = df.parse(empenterdate); earliestemp = empname; catch (ParseException e) { e.printstacktrace(); // 输出 key 为部门名称和 value 为该部门最早进入公司员工 context.write(key, new Text("The earliest emp of dept:" + earliestemp + ", Enter date:" + new SimpleDateFormat("yyyy-MM-dd").format(earliestDate))); 第 17 页共 57 页

18 @Override public int run(string[] args) throws Exception { // 实例化作业对象, 设置作业名称 Job job = new Job(getConf(), "Q3DeptEarliestEmp"); job.setjobname("q3deptearliestemp"); // 设置 Mapper 和 Reduce 类 job.setjarbyclass(q3deptearliestemp.class); job.setmapperclass(mapclass.class); job.setreducerclass(reduce.class); // 设置输入格式类 job.setinputformatclass(textinputformat.class); // 设置输出格式类 job.setoutputformatclass(textoutputformat.class); job.setoutputkeyclass(text.class); job.setoutputvalueclass(text.class); // 第 1 个参数为缓存的部门数据路径 第 2 个参数为员工数据路径和第三个参数为输出路径 String[] otherargs = new GenericOptionsParser(job.getConfiguration(), args).getremainingargs(); DistributedCache.addCacheFile(new Path(otherArgs[0]).toUri(), job.getconfiguration()); FileInputFormat.addInputPath(job, new Path(otherArgs[1])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[2])); job.waitforcompletion(true); return job.issuccessful()? 0 : 1; /** * 主方法, 执行入口 args 输入参数 */ public static void main(string[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new Q3DeptEarliestEmp(), args); System.exit(res); 第 18 页共 57 页

19 3.3.4 编译并打包代码 进入 /app/hadoop-1.1.2/myclass/class6 目录中新建 Q3DeptEarliestEmp.java 程序代码 ( 代码页可以使用 /home/shiyanlou/install-pack/class6/q3deptearliestemp.java 文件 ) cd /app/hadoop-1.1.2/myclass/class6 vi Q3DeptEarliestEmp.java 编译代码 javac -classpath../../hadoop-core jar:../../lib/commons-cli-1.2.jar Q3DeptEarliestEmp.java 把编译好的代码打成 jar 包, 如果不打成 jar 形式运行会提示 class 无法找到的错误 jar cvf./q3deptearliestemp.jar./q3deptear*.class mv *.jar../.. rm Q3DeptEar*.class 运行并查看结果 运行 Q3DeptEarliestEmp 时需要输入部门数据路径 员工数据路径和输出路径三个参数, 需要注意的是 hdfs 的路径参数路径需要全路径, 否则运行会报错 : 部门数据路径 :hdfs://hadoop:9000/class6/input/dept, 部门数据将缓存在各运行任务的节点内容中, 可以提供处理的效率 员工数据路径 :hdfs://hadoop:9000/class6/input/emp 输出路径 :hdfs://hadoop:9000/class6/out3 运行如下命令 : cd /app/hadoop 第 19 页共 57 页

20 hadoop jar Q3DeptEarliestEmp.jar Q3DeptEarliestEmp hdfs://hadoop:9000/class6/input/dept hdfs://hadoop:9000/class6/input/emp hdfs://hadoop:9000/class6/out3 运行成功后, 刷新 CentOS HDFS 中的输出路径 /class6/out3 目录 hadoop fs -ls /class6/out3 hadoop fs -cat /class6/out3/part-r 打开 part-r 文件, 可以看到运行结果 : ACCOUNTING The earliest emp of dept:clark, Enter date: RESEARCH The earliest emp of dept:smith, Enter date: SALES The earliest emp of dept:allen, Enter date: 测试例子 4: 求各个城市的员工的总工资 问题分析 求各个城市员工的总工资, 需要得到各个城市所有员工的工资, 通过对各个城市所有员工工资求和得到总工资 首先和测试例子 1 类似在 Mapper 的 Setup 阶段缓存部门对应所在城市数据, 然后在 Mapper 阶段抽取出 key 为城市名称 ( 利用缓存数据把部门编号对应为所在城市名称 ), value 为员工工资, 接着在 Shuffle 阶段把传过来的数据处理为城市名称对应该城市所有员工工资, 最后在 Reduce 中按照城市归组, 遍历城市所有员工, 求出工资总数并输出 第 20 页共 57 页

21 3.4.2 处理流程图 编写代码 import java.io.bufferedreader; import java.io.filereader; import java.io.ioexception; import java.util.hashmap; import java.util.map; import org.apache.hadoop.conf.configuration; import org.apache.hadoop.conf.configured; import org.apache.hadoop.filecache.distributedcache; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.longwritable; import org.apache.hadoop.io.text; import org.apache.hadoop.mapreduce.job; import org.apache.hadoop.mapreduce.mapper; import org.apache.hadoop.mapreduce.reducer; import org.apache.hadoop.mapreduce.lib.input.fileinputformat; import org.apache.hadoop.mapreduce.lib.input.textinputformat; import org.apache.hadoop.mapreduce.lib.output.fileoutputformat; import org.apache.hadoop.mapreduce.lib.output.textoutputformat; import org.apache.hadoop.util.genericoptionsparser; import org.apache.hadoop.util.tool; import org.apache.hadoop.util.toolrunner; public class Q4SumCitySalary extends Configured implements Tool { 第 21 页共 57 页

22 public static class MapClass extends Mapper<LongWritable, Text, Text, Text> { // 用于缓存 dept 文件中的数据 private Map<String, String> deptmap = new HashMap<String, String>(); private String[] kv; // 此方法会在 Map protected void setup(context context) throws IOException, InterruptedException { BufferedReader in = null; try { // 从当前作业中获取要缓存的文件 Path[] paths = DistributedCache.getLocalCacheFiles(context.getConfiguration()); String deptidname = null; for (Path path : paths) { if (path.tostring().contains("dept")) { in = new BufferedReader(new FileReader(path.toString())); while (null!= (deptidname = in.readline())) { // 对部门文件字段进行拆分并缓存到 deptmap 中 // 其中 Map 中 key 为部门编号,value 为所在城市名称 deptmap.put(deptidname.split(",")[0], deptidname.split(",")[2]); catch (IOException e) { e.printstacktrace(); finally { try { if (in!= null) { in.close(); catch (IOException e) { e.printstacktrace(); public void map(longwritable key, Text value, Context context) throws IOException, InterruptedException { // 对员工文件字段进行拆分 kv = value.tostring().split(","); // map join: 在 map 阶段过滤掉不需要的数据, 输出 key 为城市名称和 value 为员工工资 if (deptmap.containskey(kv[7])) { 第 22 页共 57 页

23 if (null!= kv[5] &&!"".equals(kv[5].tostring())) { context.write(new Text(deptMap.get(kv[7].trim())), new Text(kv[5].trim())); public static class Reduce extends Reducer<Text, Text, Text, LongWritable> { public void reduce(text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { // 对同一城市的员工工资进行求和 long sumsalary = 0; for (Text val : values) { sumsalary += Long.parseLong(val.toString()); // 输出 key 为城市名称和 value 为该城市工资总和 context.write(key, new public int run(string[] args) throws Exception { // 实例化作业对象, 设置作业名称 Job job = new Job(getConf(), "Q4SumCitySalary"); job.setjobname("q4sumcitysalary"); // 设置 Mapper 和 Reduce 类 job.setjarbyclass(q4sumcitysalary.class); job.setmapperclass(mapclass.class); job.setreducerclass(reduce.class); // 设置输入格式类 job.setinputformatclass(textinputformat.class); // 设置输出格式类 job.setoutputformatclass(textoutputformat.class); job.setoutputkeyclass(text.class); job.setoutputvalueclass(text.class); // 第 1 个参数为缓存的部门数据路径 第 2 个参数为员工数据路径和第 3 个参数为输出路径 String[] otherargs = new GenericOptionsParser(job.getConfiguration(), args).getremainingargs(); DistributedCache.addCacheFile(new Path(otherArgs[0]).toUri(), 第 23 页共 57 页

24 job.getconfiguration()); FileInputFormat.addInputPath(job, new Path(otherArgs[1])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[2])); job.waitforcompletion(true); return job.issuccessful()? 0 : 1; /** * 主方法, 执行入口 args 输入参数 */ public static void main(string[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new Q4SumCitySalary(), args); System.exit(res); 编译并打包代码 进入 /app/hadoop-1.1.2/myclass/class6 目录中新建 Q4SumCitySalary.java 程序代码 ( 代码页可以使用 /home/shiyanlou/install-pack/class6/q4sumcitysalary.java 文件 ) cd /app/hadoop-1.1.2/myclass/class6 vi Q4SumCitySalary.java 编译代码 javac -classpath../../hadoop-core jar:../../lib/commons-cli-1.2.jar Q4SumCitySalary.java 把编译好的代码打成 jar 包, 如果不打成 jar 形式运行会提示 class 无法找到的错误 jar cvf./q4sumcitysalary.jar./q4sumcity*.class mv *.jar../.. rm Q4SumCity*.class 第 24 页共 57 页

25 3.4.5 运行并查看结果 运行 Q4SumCitySalary 时需要输入部门数据路径 员工数据路径和输出路径三个参数, 需要注意的是 hdfs 的路径参数路径需要全路径, 否则运行会报错 : 部门数据路径 :hdfs://hadoop:9000/class6/input/dept, 部门数据将缓存在各运行任务的节点内容中, 可以提供处理的效率 员工数据路径 :hdfs://hadoop:9000/class6/input/emp 输出路径 :hdfs://hadoop:9000/class6/out4 运行如下命令 : cd /app/hadoop hadoop jar Q4SumCitySalary.jar Q4SumCitySalary hdfs://hadoop:9000/class6/input/dept hdfs://hadoop:9000/class6/input/emp hdfs://hadoop:9000/class6/out4 运行成功后, 刷新 CentOS HDFS 中的输出路径 /class6/out4 目录 hadoop fs -ls /class6/out4 hadoop fs -cat /class6/out4/part-r 第 25 页共 57 页

26 打开 part-r 文件, 可以看到运行结果 : CHICAGO 9400 DALLAS 6775 NEW YORK 测试例子 5: 列出工资比上司高的员工姓名及其工资 问题分析 求工资比上司高的员工姓名及工资, 需要得到上司工资及上司所有下属员工, 通过比较他们工资高低得到比上司工资高的员工 在 Mapper 阶段输出经理数据和员工对应经理表数据, 其中经理数据 key 为员工编号 value 为 "M, 该员工工资 ", 员工对应经理表数据 key 为经理编号 value 为 "E, 该员工姓名, 该员工工资 "; 然后在 Shuffle 阶段把传过来的经理数据和员工对应经理表数据进行归组, 如编号为 7698 员工,value 中标志 M 为自己工资,value 中标志 E 为其下属姓名及工资 ; 最后在 Reduce 中遍历比较员工与经理工资高低, 输出工资高于经理的员工 处理流程图 第 26 页共 57 页

27 3.5.3 编写代码 import java.io.ioexception; import java.util.hashmap; import org.apache.hadoop.conf.configuration; import org.apache.hadoop.conf.configured; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.longwritable; import org.apache.hadoop.io.text; import org.apache.hadoop.mapreduce.job; import org.apache.hadoop.mapreduce.mapper; import org.apache.hadoop.mapreduce.reducer; import org.apache.hadoop.mapreduce.lib.input.fileinputformat; import org.apache.hadoop.mapreduce.lib.input.textinputformat; import org.apache.hadoop.mapreduce.lib.output.fileoutputformat; import org.apache.hadoop.mapreduce.lib.output.textoutputformat; import org.apache.hadoop.util.genericoptionsparser; import org.apache.hadoop.util.tool; import org.apache.hadoop.util.toolrunner; public class Q5EarnMoreThanManager extends Configured implements Tool { public static class MapClass extends Mapper<LongWritable, Text, Text, Text> { public void map(longwritable key, Text value, Context context) throws IOException, InterruptedException { // 对员工文件字段进行拆分 String[] kv = value.tostring().split(","); // 输出经理表数据, 其中 key 为员工编号和 value 为 M+ 该员工工资 context.write(new Text(kv[0].toString()), new Text("M," + kv[5])); // 输出员工对应经理表数据, 其中 key 为经理编号和 value 为 (E, 该员工姓名, 该员工工资 ) if (null!= kv[3] &&!"".equals(kv[3].tostring())) { context.write(new Text(kv[3].toString()), new Text("E," + kv[1] + "," + kv[5])); public static class Reduce extends Reducer<Text, Text, Text, Text> { public void reduce(text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { // 定义员工姓名 工资和存放部门员工 Map 第 27 页共 57 页

28 String empname; long empsalary = 0; HashMap<String, Long> empmap = new HashMap<String, Long>(); // 定义经理工资变量 long mgrsalary = 0; for (Text val : values) { if (val.tostring().startswith("e")) { // 当是员工标示时, 获取该员工对应的姓名和工资并放入 Map 中 empname = val.tostring().split(",")[1]; empsalary = Long.parseLong(val.toString().split(",")[2]); empmap.put(empname, empsalary); else { // 当时经理标志时, 获取该经理工资 mgrsalary = Long.parseLong(val.toString().split(",")[1]); // 遍历该经理下属, 比较员工与经理工资高低, 输出工资高于经理的员工 for (java.util.map.entry<string, Long> entry : empmap.entryset()) { if (entry.getvalue() > mgrsalary) { context.write(new Text(entry.getKey()), new Text("" + public int run(string[] args) throws Exception { // 实例化作业对象, 设置作业名称 Job job = new Job(getConf(), "Q5EarnMoreThanManager"); job.setjobname("q5earnmorethanmanager"); // 设置 Mapper 和 Reduce 类 job.setjarbyclass(q5earnmorethanmanager.class); job.setmapperclass(mapclass.class); job.setreducerclass(reduce.class); // 设置输入格式类 job.setinputformatclass(textinputformat.class); // 设置输出格式类 job.setoutputformatclass(textoutputformat.class); job.setoutputkeyclass(text.class); job.setoutputvalueclass(text.class); 第 28 页共 57 页

29 // 第 1 个参数为员工数据路径和第 2 个参数为输出路径 String[] otherargs = new GenericOptionsParser(job.getConfiguration(), args).getremainingargs(); FileInputFormat.addInputPath(job, new Path(otherArgs[0])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); job.waitforcompletion(true); return job.issuccessful()? 0 : 1; /** * 主方法, 执行入口 args 输入参数 */ public static void main(string[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new Q5EarnMoreThanManager(), args); System.exit(res); 编译并打包代码 进入 /app/hadoop-1.1.2/myclass/class6 目录中新建 Q5EarnMoreThanManager.java 程序代码 ( 代码页可以使用 /home/shiyanlou/install-pack/class6/q5earnmorethanmanager.java 文件 ) cd /app/hadoop-1.1.2/myclass/class6 vi Q5EarnMoreThanManager.java 编译代码 javac -classpath../../hadoop-core jar:../../lib/commons-cli-1.2.jar Q5EarnMoreThanManager.java 把编译好的代码打成 jar 包, 如果不打成 jar 形式运行会提示 class 无法找到的错误 jar cvf./q5earnmorethanmanager.jar./q5earnmore*.class mv *.jar../.. rm Q5EarnMore*.class 第 29 页共 57 页

30 3.5.5 运行并查看结果 运行 Q5EarnMoreThanManager 运行的员工数据路径和输出路径两个参数, 需要注意的是 hdfs 的路径参数路径需要全路径, 否则运行会报错 : 员工数据路径 :hdfs://hadoop:9000/class6/input/emp 输出路径 :hdfs://hadoop:9000/class6/out5 运行如下命令 : cd /app/hadoop hadoop jar Q5EarnMoreThanManager.jar Q5EarnMoreThanManager hdfs://hadoop:9000/class6/input/emp hdfs://hadoop:9000/class6/out5 运行成功后, 刷新 CentOS HDFS 中的输出路径 /class6/out5 目录 hadoop fs -ls /class6/out5 hadoop fs -cat /class6/out5/part-r 打开 part-r 文件, 可以看到运行结果 : FORD 3000 第 30 页共 57 页

31 3.6 测试例子 6: 列出工资比公司平均工资要高的员工姓名及其工资 问题分析 求工资比公司平均工资要高的员工姓名及工资, 需要得到公司的平均工资和所有员工工资, 通过比较得出工资比平均工资高的员工姓名及工资 这个问题可以分两个作业进行解决, 先求出公司的平均工资, 然后与所有员工进行比较得到结果 ; 也可以在一个作业进行解决, 这里就得使用作业 setnumreducetasks 方法, 设置 Reduce 任务数为 1, 保证每次运行一个 reduce 任务, 从而能先求出平均工资, 然后进行比较得出结果 在 Mapper 阶段输出两份所有员工数据, 其中一份 key 为 0 value 为该员工工资, 另外一份 key 为 0 value 为 " 该员工姓名, 员工工资 "; 然后在 Shuffle 阶段把传过来数据按照 key 进行归组, 在该任务中有 key 值为 0 和 1 两组数据 ; 最后在 Reduce 中对 key 值 0 的所有员工求工资总数和员工数, 获得平均工资 ; 对 key 值 1, 比较员工与平均工资的大小, 输出比平均工资高的员工和对应的工资 处理流程图 第 31 页共 57 页

32 3.6.3 编写代码 import java.io.ioexception; import org.apache.hadoop.conf.configuration; import org.apache.hadoop.conf.configured; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.intwritable; import org.apache.hadoop.io.longwritable; import org.apache.hadoop.io.text; import org.apache.hadoop.mapreduce.job; import org.apache.hadoop.mapreduce.mapper; import org.apache.hadoop.mapreduce.reducer; import org.apache.hadoop.mapreduce.lib.input.fileinputformat; import org.apache.hadoop.mapreduce.lib.output.fileoutputformat; import org.apache.hadoop.mapreduce.lib.output.textoutputformat; import org.apache.hadoop.util.genericoptionsparser; import org.apache.hadoop.util.tool; import org.apache.hadoop.util.toolrunner; public class Q6HigherThanAveSalary extends Configured implements Tool { public static class MapClass extends Mapper<LongWritable, Text, IntWritable, Text> { public void map(longwritable key, Text value, Context context) throws IOException, InterruptedException { // 对员工文件字段进行拆分 String[] kv = value.tostring().split(","); // 获取所有员工数据, 其中 key 为 0 和 value 为该员工工资 context.write(new IntWritable(0), new Text(kv[5])); // 获取所有员工数据, 其中 key 为 0 和 value 为 ( 该员工姓名, 员工工资 ) context.write(new IntWritable(1), new Text(kv[1] + "," + kv[5])); public static class Reduce extends Reducer<IntWritable, Text, Text, Text> { // 定义员工工资 员工数和平均工资 private long allsalary = 0; private int allempcount = 0; private long avesalary = 0; // 定义员工工资变量 private long empsalary = 0; 第 32 页共 57 页

33 public void reduce(intwritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException { for (Text val : values) { if (0 == key.get()) { // 获取所有员工工资和员工数 allsalary += Long.parseLong(val.toString()); allempcount++; System.out.println("allEmpCount = " + allempcount); else if (1 == key.get()) { if (avesalary == 0) { avesalary = allsalary / allempcount; context.write(new Text("Average Salary = "), new Text("" + avesalary)); context.write(new Text("Following employees have salarys higher than Average:"), new Text("")); // 获取员工的平均工资 System.out.println("Employee salary = " + val.tostring()); avesalary = allsalary / allempcount; // 比较员工与平均工资的大小, 输出比平均工资高的员工和对应的工资 empsalary = Long.parseLong(val.toString().split(",")[1]); if (empsalary > avesalary) { context.write(new Text(val.toString().split(",")[0]), new Text("" + public int run(string[] args) throws Exception { // 实例化作业对象, 设置作业名称 Job job = new Job(getConf(), "Q6HigherThanAveSalary"); job.setjobname("q6higherthanavesalary"); // 设置 Mapper 和 Reduce 类 job.setjarbyclass(q6higherthanavesalary.class); job.setmapperclass(mapclass.class); job.setreducerclass(reduce.class); // 必须设置 Reduce 任务数为 1 # -D mapred.reduce.tasks = 1 // 这是该作业设置的核心, 这样才能够保证各 reduce 是串行的 job.setnumreducetasks(1); 第 33 页共 57 页

34 // 设置输出格式类 job.setmapoutputkeyclass(intwritable.class); job.setmapoutputvalueclass(text.class); // 设置输出键和值类型 job.setoutputformatclass(textoutputformat.class); job.setoutputkeyclass(text.class); job.setoutputvalueclass(longwritable.class); // 第 1 个参数为员工数据路径和第 2 个参数为输出路径 String[] otherargs = new GenericOptionsParser(job.getConfiguration(), args).getremainingargs(); FileInputFormat.addInputPath(job, new Path(otherArgs[0])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); job.waitforcompletion(true); return job.issuccessful()? 0 : 1; /** * 主方法, 执行入口 args 输入参数 */ public static void main(string[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new Q6HigherThanAveSalary(), args); System.exit(res); 编译并打包代码 进入 /app/hadoop-1.1.2/myclass/class6 目录中新建 Q5EarnMoreThanManager.java 程序代码 ( 代码页可以使用 /home/shiyanlou/install-pack/class6/q6higherthanavesalary.java 文件 ) cd /app/hadoop-1.1.2/myclass/class6 vi Q6HigherThanAveSalary.java 编译代码 javac -classpath../../hadoop-core jar:../../lib/commons-cli-1.2.jar Q6HigherThanAveSalary.java 把编译好的代码打成 jar 包, 如果不打成 jar 形式运行会提示 class 无法找到的错误 jar cvf./q6higherthanavesalary.jar./q6higherthan*.class mv *.jar../.. rm Q6HigherThan*.class 第 34 页共 57 页

35 3.6.5 运行并查看结果 运行 Q6HigherThanAveSalary 运行的员工数据路径和输出路径两个参数, 需要注意的是 hdfs 的路径参数路径需要全路径, 否则运行会报错 : 员工数据路径 :hdfs://hadoop:9000/class6/input/emp 输出路径 :hdfs://hadoop:9000/class6/out6 运行如下命令 : cd /app/hadoop hadoop jar Q6HigherThanAveSalary.jar Q6HigherThanAveSalary hdfs://hadoop:9000/class6/input/emp hdfs://hadoop:9000/class6/out6 运行成功后, 刷新 CentOS HDFS 中的输出路径 /class6/out6 目录 hadoop fs -ls /class6/out6 hadoop fs -cat /class6/out6/part-r 打开 part-r 文件, 可以看到运行结果 : Average Salary = 2077 Following employees have salarys higher than Average: 第 35 页共 57 页

36 FORD 3000 CLARK 2450 KING 5000 JONES 2975 BLAKE 测试例子 7: 列出名字以 J 开头的员工姓名及其所属部门名称 问题分析 求名字以 J 开头的员工姓名机器所属部门名称, 只需判断员工姓名是否以 J 开头 首先和问题 1 类似在 Mapper 的 Setup 阶段缓存部门数据, 然后在 Mapper 阶段判断员工姓名是否以 J 开头, 如果是抽取出员工姓名和员工所在部门编号, 利用缓存部门数据把部门编号对应为部门名称, 转换后输出结果 处理流程图 第 36 页共 57 页

37 3.7.3 编写代码 import java.io.bufferedreader; import java.io.filereader; import java.io.ioexception; import java.util.hashmap; import java.util.map; import org.apache.hadoop.conf.configuration; import org.apache.hadoop.conf.configured; import org.apache.hadoop.filecache.distributedcache; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.longwritable; import org.apache.hadoop.io.text; import org.apache.hadoop.mapreduce.job; import org.apache.hadoop.mapreduce.mapper; import org.apache.hadoop.mapreduce.lib.input.fileinputformat; import org.apache.hadoop.mapreduce.lib.input.textinputformat; import org.apache.hadoop.mapreduce.lib.output.fileoutputformat; import org.apache.hadoop.mapreduce.lib.output.textoutputformat; import org.apache.hadoop.util.genericoptionsparser; import org.apache.hadoop.util.tool; import org.apache.hadoop.util.toolrunner; public class Q7NameDeptOfStartJ extends Configured implements Tool { public static class MapClass extends Mapper<LongWritable, Text, Text, Text> { // 用于缓存 dept 文件中的数据 private Map<String, String> deptmap = new HashMap<String, String>(); private String[] kv; // 此方法会在 Map protected void setup(context context) throws IOException, InterruptedException { BufferedReader in = null; try { // 从当前作业中获取要缓存的文件 Path[] paths = DistributedCache.getLocalCacheFiles(context.getConfiguration()); String deptidname = null; for (Path path : paths) { // 对部门文件字段进行拆分并缓存到 deptmap 中 if (path.tostring().contains("dept")) { in = new BufferedReader(new FileReader(path.toString())); while (null!= (deptidname = in.readline())) { 第 37 页共 57 页

38 // 对部门文件字段进行拆分并缓存到 deptmap 中 // 其中 Map 中 key 为部门编号,value 为所在部门名称 deptmap.put(deptidname.split(",")[0], deptidname.split(",")[1]); catch (IOException e) { e.printstacktrace(); finally { try { if (in!= null) { in.close(); catch (IOException e) { e.printstacktrace(); public void map(longwritable key, Text value, Context context) throws IOException, InterruptedException { // 对员工文件字段进行拆分 kv = value.tostring().split(","); // 输出员工姓名为 J 开头的员工信息,key 为员工姓名和 value 为员工所在部门名称 if (kv[1].tostring().trim().startswith("j")) { context.write(new Text(kv[1].trim()), new public int run(string[] args) throws Exception { // 实例化作业对象, 设置作业名称 Job job = new Job(getConf(), "Q7NameDeptOfStartJ"); job.setjobname("q7namedeptofstartj"); // 设置 Mapper 和 Reduce 类 job.setjarbyclass(q7namedeptofstartj.class); job.setmapperclass(mapclass.class); // 设置输入格式类 job.setinputformatclass(textinputformat.class); 第 38 页共 57 页

39 // 设置输出格式类 job.setoutputformatclass(textoutputformat.class); job.setoutputkeyclass(text.class); job.setoutputvalueclass(text.class); // 第 1 个参数为缓存的部门数据路径 第 2 个参数为员工数据路径和第 3 个参数为输出路径 String[] otherargs = new GenericOptionsParser(job.getConfiguration(), args).getremainingargs(); DistributedCache.addCacheFile(new Path(otherArgs[0]).toUri(), job.getconfiguration()); FileInputFormat.addInputPath(job, new Path(otherArgs[1])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[2])); job.waitforcompletion(true); return job.issuccessful()? 0 : 1; /** * 主方法, 执行入口 args 输入参数 */ public static void main(string[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new Q7NameDeptOfStartJ(), args); System.exit(res); 编译并打包代码 进入 /app/hadoop-1.1.2/myclass/class6 目录中新建 Q7NameDeptOfStartJ.java 程序代码 ( 代码页可以使用 /home/shiyanlou/install-pack/class6/q7namedeptofstartj.java 文件 ) cd /app/hadoop-1.1.2/myclass/class6 vi Q7NameDeptOfStartJ.java 编译代码 javac -classpath../../hadoop-core jar:../../lib/commons-cli-1.2.jar Q7NameDeptOfStartJ.java 把编译好的代码打成 jar 包, 如果不打成 jar 形式运行会提示 class 无法找到的错误 jar cvf./q7namedeptofstartj.jar./q7namedept*.class mv *.jar../.. rm Q7NameDept*.class 第 39 页共 57 页

40 3.7.5 运行并查看结果 运行 Q7NameDeptOfStartJ 时需要输入部门数据路径 员工数据路径和输出路径三个参数, 需要注意的是 hdfs 的路径参数路径需要全路径, 否则运行会报错 : 部门数据路径 :hdfs://hadoop:9000/class6/input/dept, 部门数据将缓存在各运行任务的节点内容中, 可以提供处理的效率 员工数据路径 :hdfs://hadoop:9000/class6/input/emp 输出路径 :hdfs://hadoop:9000/class6/out7 运行如下命令 : cd /app/hadoop hadoop jar Q7NameDeptOfStartJ.jar Q7NameDeptOfStartJ hdfs://hadoop:9000/class6/input/dept hdfs://hadoop:9000/class6/input/emp hdfs://hadoop:9000/class6/out7 运行成功后, 刷新 CentOS HDFS 中的输出路径 /class6/out7 目录 hadoop fs -ls /class6/out7 hadoop fs -cat /class6/out7/part-r 打开 part-r 文件, 可以看到运行结果 : JAMES SALES 第 40 页共 57 页

41 JONES RESEARCH 3.8 测试例子 8: 列出工资最高的头三名员工姓名及其工资 问题分析 求工资最高的头三名员工姓名及工资, 可以通过冒泡法得到 在 Mapper 阶段输出经理数据和员工对应经理表数据, 其中经理数据 key 为 0 值 value 为 " 员工姓名, 员工工资 "; 最后在 Reduce 中通过冒泡法遍历所有员工, 比较员工工资多少, 求出前三名 处理流程图 编写代码 import java.io.ioexception; import org.apache.hadoop.conf.configuration; import org.apache.hadoop.conf.configured; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.intwritable; import org.apache.hadoop.io.longwritable; import org.apache.hadoop.io.text; import org.apache.hadoop.mapreduce.job; 第 41 页共 57 页

42 import org.apache.hadoop.mapreduce.mapper; import org.apache.hadoop.mapreduce.reducer; import org.apache.hadoop.mapreduce.lib.input.fileinputformat; import org.apache.hadoop.mapreduce.lib.input.textinputformat; import org.apache.hadoop.mapreduce.lib.output.fileoutputformat; import org.apache.hadoop.mapreduce.lib.output.textoutputformat; import org.apache.hadoop.util.genericoptionsparser; import org.apache.hadoop.util.tool; import org.apache.hadoop.util.toolrunner; public class Q8SalaryTop3Salary extends Configured implements Tool { public static class MapClass extends Mapper<LongWritable, Text, IntWritable, Text> { public void map(longwritable key, Text value, Context context) throws IOException, InterruptedException { // 对员工文件字段进行拆分 String[] kv = value.tostring().split(","); // 输出 key 为 0 和 value 为员工姓名 +","+ 员工工资 context.write(new IntWritable(0), new Text(kv[1].trim() + "," + kv[5].trim())); public static class Reduce extends Reducer<IntWritable, Text, Text, Text> { public void reduce(intwritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException { // 定义工资前三员工姓名 String empname; String firstempname = ""; String secondempname = ""; String thirdempname = ""; // 定义工资前三工资 long empsalary = 0; long firstempsalary = 0; long secondempsalary = 0; long thirdempsalary = 0; // 通过冒泡法遍历所有员工, 比较员工工资多少, 求出前三名 for (Text val : values) { empname = val.tostring().split(",")[0]; empsalary = Long.parseLong(val.toString().split(",")[1]); 第 42 页共 57 页

43 if(empsalary > firstempsalary) { thirdempname = secondempname; thirdempsalary = secondempsalary; secondempname = firstempname; secondempsalary = firstempsalary; firstempname = empname; firstempsalary = empsalary; else if (empsalary > secondempsalary) { thirdempname = secondempname; thirdempsalary = secondempsalary; secondempname = empname; secondempsalary = empsalary; else if (empsalary > thirdempsalary) { thirdempname = empname; thirdempsalary = empsalary; // 输出工资前三名信息 context.write(new Text( "First employee name:" + firstempname), new Text("Salary:" + firstempsalary)); context.write(new Text( "Second employee name:" + secondempname), new Text("Salary:" + secondempsalary)); context.write(new Text( "Third employee name:" + thirdempname), new Text("Salary:" + public int run(string[] args) throws Exception { // 实例化作业对象, 设置作业名称 Job job = new Job(getConf(), "Q8SalaryTop3Salary"); job.setjobname("q8salarytop3salary"); // 设置 Mapper 和 Reduce 类 job.setjarbyclass(q8salarytop3salary.class); job.setmapperclass(mapclass.class); job.setreducerclass(reduce.class); job.setmapoutputkeyclass(intwritable.class); job.setmapoutputvalueclass(text.class); // 设置输入格式类 job.setinputformatclass(textinputformat.class); // 设置输出格式类 job.setoutputkeyclass(text.class); 第 43 页共 57 页

44 job.setoutputformatclass(textoutputformat.class); job.setoutputvalueclass(text.class); // 第 1 个参数为员工数据路径和第 2 个参数为输出路径 String[] otherargs = new GenericOptionsParser(job.getConfiguration(), args).getremainingargs(); FileInputFormat.addInputPath(job, new Path(otherArgs[0])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); job.waitforcompletion(true); return job.issuccessful()? 0 : 1; /** * 主方法, 执行入口 args 输入参数 */ public static void main(string[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new Q8SalaryTop3Salary(), args); System.exit(res); 编译并打包代码 进入 /app/hadoop-1.1.2/myclass/class6 目录中新建 Q8SalaryTop3Salary.java 程序代码 ( 代码页可以使用 /home/shiyanlou/install-pack/class6/q8salarytop3salary.java 文件 ) cd /app/hadoop-1.1.2/myclass/class6 vi Q8SalaryTop3Salary.java 编译代码 javac -classpath../../hadoop-core jar:../../lib/commons-cli-1.2.jar Q8SalaryTop3Salary.java 把编译好的代码打成 jar 包, 如果不打成 jar 形式运行会提示 class 无法找到的错误 jar cvf./q8salarytop3salary.jar./q8salarytop3*.class mv *.jar../.. rm Q8SalaryTop3*.class 第 44 页共 57 页

45 3.8.5 运行并查看结果 运行 Q8SalaryTop3Salary 运行的员工数据路径和输出路径两个参数, 需要注意的是 hdfs 的路径参数路径需要全路径, 否则运行会报错 : 员工数据路径 :hdfs://hadoop:9000/class6/input/emp 输出路径 :hdfs://hadoop:9000/class6/out8 运行如下命令 : cd /app/hadoop hadoop jar Q8SalaryTop3Salary.jar Q8SalaryTop3Salary hdfs://hadoop:9000/class6/input/emp hdfs://hadoop:9000/class6/out8 运行成功后, 刷新 CentOS HDFS 中的输出路径 /class6/out8 目录 hadoop fs -ls /class6/out8 hadoop fs -cat /class6/out8/part-r 打开 part-r 文件, 可以看到运行结果 : First employee name:king Salary:5000 Second employee name:ford Salary:3000 第 45 页共 57 页

46 Third employee name:jones Salary: 测试例子 9: 将全体员工按照总收入 ( 工资 + 提成 ) 从高到低排列 问题分析 求全体员工总收入降序排列, 获得所有员工总收入并降序排列即可 在 Mapper 阶段输出所有员工总工资数据, 其中 key 为员工总工资 value 为员工姓名, 在 Mapper 阶段的最后会先调用 job.setpartitionerclass 对数据进行分区, 每个分区映射到一个 reducer, 每个分区内又调用 job.setsortcomparatorclass 设置的 key 比较函数类排序 由于在本作业中 Map 的 key 只有 0 值, 故能实现对所有数据进行排序 处理流程图 编写代码 import java.io.ioexception; import org.apache.hadoop.conf.configuration; import org.apache.hadoop.conf.configured; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.intwritable; import org.apache.hadoop.io.longwritable; 第 46 页共 57 页

47 import org.apache.hadoop.io.text; import org.apache.hadoop.io.writablecomparable; import org.apache.hadoop.mapreduce.job; import org.apache.hadoop.mapreduce.mapper; import org.apache.hadoop.mapreduce.lib.input.fileinputformat; import org.apache.hadoop.mapreduce.lib.output.fileoutputformat; import org.apache.hadoop.util.genericoptionsparser; import org.apache.hadoop.util.tool; import org.apache.hadoop.util.toolrunner; public class Q9EmpSalarySort extends Configured implements Tool { public static class MapClass extends Mapper<LongWritable, Text, IntWritable, Text> { public void map(longwritable key, Text value, Context context) throws IOException, InterruptedException { // 对员工文件字段进行拆分 String[] kv = value.tostring().split(","); // 输出 key 为员工所有工资和 value 为员工姓名 int empallsalary = "".equals(kv[6])? Integer.parseInt(kv[5]) : Integer.parseInt(kv[5]) + Integer.parseInt(kv[6]); context.write(new IntWritable(empAllSalary), new Text(kv[1])); /** * 递减排序算法 */ public static class DecreaseComparator extends IntWritable.Comparator { public int compare(writablecomparable a, WritableComparable b) { return -super.compare(a, b); public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) { return -super.compare(b1, s1, l1, b2, s2, public int run(string[] args) throws Exception { // 实例化作业对象, 设置作业名称 Job job = new Job(getConf(), "Q9EmpSalarySort"); job.setjobname("q9empsalarysort"); 第 47 页共 57 页

48 // 设置 Mapper 和 Reduce 类 job.setjarbyclass(q9empsalarysort.class); job.setmapperclass(mapclass.class); // 设置输出格式类 job.setmapoutputkeyclass(intwritable.class); job.setmapoutputvalueclass(text.class); job.setsortcomparatorclass(decreasecomparator.class); // 第 1 个参数为员工数据路径和第 2 个参数为输出路径 String[] otherargs = new GenericOptionsParser(job.getConfiguration(), args).getremainingargs(); FileInputFormat.addInputPath(job, new Path(otherArgs[0])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); job.waitforcompletion(true); return job.issuccessful()? 0 : 1; /** * 主方法, 执行入口 args 输入参数 */ public static void main(string[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new Q9EmpSalarySort(), args); System.exit(res); 编译并打包代码 进入 /app/hadoop-1.1.2/myclass/class6 目录中新建 Q9EmpSalarySort.java 程序代码 ( 代码页可以使用 /home/shiyanlou/install-pack/class6/q9empsalarysort.java 文件 ) cd /app/hadoop-1.1.2/myclass/class6 vi Q9EmpSalarySort.java 编译代码 javac -classpath../../hadoop-core jar:../../lib/commons-cli-1.2.jar Q9EmpSalarySort.java 把编译好的代码打成 jar 包, 如果不打成 jar 形式运行会提示 class 无法找到的错误 jar cvf./q9empsalarysort.jar./q9empsalary*.class mv *.jar../.. rm Q9EmpSalary*.class 第 48 页共 57 页

49 3.9.5 运行并查看结果 运行 Q9EmpSalarySort 运行的员工数据路径和输出路径两个参数, 需要注意的是 hdfs 的路径参数路径需要全路径, 否则运行会报错 : 员工数据路径 :hdfs://hadoop:9000/class6/input/emp 输出路径 :hdfs://hadoop:9000/class6/out9 运行如下命令 : cd /app/hadoop hadoop jar Q9EmpSalarySort.jar Q9EmpSalarySort hdfs://hadoop:9000/class6/input/emp hdfs://hadoop:9000/class6/out9 运行成功后, 刷新 CentOS HDFS 中的输出路径 /class6/out9 目录 hadoop fs -ls /class6/out9 hadoop fs -cat /class6/out9/part-r 打开 part-r 文件, 可以看到运行结果 : 5000 KING 3000 FORD 2975 JONES 第 49 页共 57 页

50 2850 BLAKE 测试例子 10: 求任何两名员工信息传递所需要经过的中间节点数 问题分析 该公司所有员工可以形成入下图的树形结构, 求两个员工的沟通的中间节点数, 可转换在员工树中求两个节点连通所经过的节点数, 即从其中一节点到汇合节点经过节点数加上另一节点到汇合节点经过节点数 例如求 M 到 Q 所需节点数, 可以先找出 M 到 A 经过的节点数, 然后找出 Q 到 A 经过的节点数, 两者相加得到 M 到 Q 所需节点数 在作业中首先在 Mapper 阶段所有员工数据, 其中经理数据 key 为 0 值 value 为 " 员工编号, 员工经理编号 ", 然后在 Reduce 阶段把所有员工放到员工列表和员工对应经理链表 Map 中, 最后在 Reduce 的 Cleanup 中按照上面说所算法对任意两个员工计算出沟通的路径长度并输出 第 50 页共 57 页

51 处理流程图 编写代码 import java.io.ioexception; import java.util.arraylist; import java.util.hashmap; import java.util.list; import java.util.map; import org.apache.hadoop.conf.configuration; import org.apache.hadoop.conf.configured; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.intwritable; import org.apache.hadoop.io.longwritable; import org.apache.hadoop.io.nullwritable; import org.apache.hadoop.io.text; import org.apache.hadoop.mapreduce.job; import org.apache.hadoop.mapreduce.mapper; import org.apache.hadoop.mapreduce.reducer; import org.apache.hadoop.mapreduce.lib.input.fileinputformat; import org.apache.hadoop.mapreduce.lib.output.fileoutputformat; import org.apache.hadoop.mapreduce.lib.output.textoutputformat; import org.apache.hadoop.util.genericoptionsparser; import org.apache.hadoop.util.tool; import org.apache.hadoop.util.toolrunner; public class Q10MiddlePersonsCountForComm extends Configured implements Tool { 第 51 页共 57 页

52 public static class MapClass extends Mapper<LongWritable, Text, IntWritable, Text> { public void map(longwritable key, Text value, Context context) throws IOException, InterruptedException { // 对员工文件字段进行拆分 String[] kv = value.tostring().split(","); // 输出 key 为 0 和 value 为员工编号 +","+ 员工经理编号 context.write(new IntWritable(0), new Text(kv[0] + "," + ("".equals(kv[3])? " " : kv[3]))); public static class Reduce extends Reducer<IntWritable, Text, NullWritable, Text> { // 定义员工列表和员工对应经理 Map List<String> employeelist = new ArrayList<String>(); Map<String, String> employeetomanagermap = new HashMap<String, String>(); public void reduce(intwritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException { // 在 reduce 阶段把所有员工放到员工列表和员工对应经理 Map 中 for (Text value : values) { employeelist.add(value.tostring().split(",")[0].trim()); employeetomanagermap.put(value.tostring().split(",")[0].trim(), protected void cleanup(context context) throws IOException, InterruptedException { int totalemployee = employeelist.size(); int i, j; int distance; System.out.println(employeeList); System.out.println(employeeToManagerMap); // 对任意两个员工计算出沟通的路径长度并输出 for (i = 0; i < (totalemployee - 1); i++) { for (j = (i + 1); j < totalemployee; j++) { distance = calculatedistance(i, j); String value = employeelist.get(i) + " and " + employeelist.get(j) + " = " + distance; context.write(nullwritable.get(), new Text(value)); 第 52 页共 57 页

53 /** * 该公司可以由所有员工形成树形结构, 求两个员工的沟通的中间节点数, 可以转换在员工树中两员工之间的距离 * 由于在树中任意两点都会在某上级节点汇合, 根据该情况设计了如下算法 */ private int calculatedistance(int i, int j) { String employeea = employeelist.get(i); String employeeb = employeelist.get(j); int distance = 0; // 如果 A 是 B 的经理, 反之亦然 if (employeetomanagermap.get(employeea).equals(employeeb) employeetomanagermap.get(employeeb).equals(employeea)) { distance = 0; // A 和 B 在同一经理下 else if (employeetomanagermap.get(employeea).equals( employeetomanagermap.get(employeeb))) { distance = 0; else { // 定义 A 和 B 对应经理链表 List<String> employeea_managerlist = new ArrayList<String>(); List<String> employeeb_managerlist = new ArrayList<String>(); // 获取从 A 开始经理链表 employeea_managerlist.add(employeea); String current = employeea; while (false == employeetomanagermap.get(current).isempty()) { current = employeetomanagermap.get(current); employeea_managerlist.add(current); // 获取从 B 开始经理链表 employeeb_managerlist.add(employeeb); current = employeeb; while (false == employeetomanagermap.get(current).isempty()) { current = employeetomanagermap.get(current); employeeb_managerlist.add(current); int ii = 0, jj = 0; String currenta_manager, currentb_manager; boolean found = false; // 遍历 A 与 B 开始经理链表, 找出汇合点计算 for (ii = 0; ii < employeea_managerlist.size(); ii++) { 第 53 页共 57 页

54 currenta_manager = employeea_managerlist.get(ii); for (jj = 0; jj < employeeb_managerlist.size(); jj++) { currentb_manager = employeeb_managerlist.get(jj); if (currenta_manager.equals(currentb_manager)) { found = true; break; if (found) { break; // 最后获取两只之前的路径 distance = ii + jj - 1; return public int run(string[] args) throws Exception { // 实例化作业对象, 设置作业名称 Job job = new Job(getConf(), "Q10MiddlePersonsCountForComm"); job.setjobname("q10middlepersonscountforcomm"); // 设置 Mapper 和 Reduce 类 job.setjarbyclass(q10middlepersonscountforcomm.class); job.setmapperclass(mapclass.class); job.setreducerclass(reduce.class); // 设置 Mapper 输出格式类 job.setmapoutputkeyclass(intwritable.class); job.setmapoutputvalueclass(text.class); // 设置 Reduce 输出键和值类型 job.setoutputformatclass(textoutputformat.class); job.setoutputkeyclass(nullwritable.class); job.setoutputvalueclass(text.class); // 第 1 个参数为员工数据路径和第 2 个参数为输出路径 String[] otherargs = new GenericOptionsParser(job.getConfiguration(), args).getremainingargs(); FileInputFormat.addInputPath(job, new Path(otherArgs[0])); 第 54 页共 57 页

55 FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); job.waitforcompletion(true); return job.issuccessful()? 0 : 1; /** * 主方法, 执行入口 args 输入参数 */ public static void main(string[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new Q10MiddlePersonsCountForComm(), args); System.exit(res); 编译并打包代码 进入 /app/hadoop-1.1.2/myclass/class6 目录中新建 Q10MiddlePersonsCountForComm.java 程序代码 ( 代码页可以使用 /home/shiyanlou/install-pack/class6/q10middlepersonscountforcomm.java 文件 ) cd /app/hadoop-1.1.2/myclass/class6 vi Q10MiddlePersonsCountForComm.java 编译代码 javac -classpath../../hadoop-core jar:../../lib/commons-cli-1.2.jar Q10MiddlePersonsCountForComm.java 把编译好的代码打成 jar 包, 如果不打成 jar 形式运行会提示 class 无法找到的错误 jar cvf./q10middlepersonscountforcomm.jar./q10middlepersons*.class mv *.jar../.. rm Q10MiddlePersons*.class 第 55 页共 57 页

56 运行并查看结果 运行 Q10MiddlePersonsCountForComm 运行的员工数据路径和输出路径两个参数, 需要注意的是 hdfs 的路径参数路径需要全路径, 否则运行会报错 : 员工数据路径 :hdfs://hadoop:9000/class6/input/emp 输出路径 :hdfs://hadoop:9000/class6/out10 运行如下命令 : cd /app/hadoop hadoop jar Q10MiddlePersonsCountForComm.jar Q10MiddlePersonsCountForComm hdfs://hadoop:9000/class6/input/emp hdfs://hadoop:9000/class6/out10 运行成功后, 刷新 CentOS HDFS 中的输出路径 /class6/out10 目录 hadoop fs -ls /class6/out10 hadoop fs -cat /class6/out10/part-r 第 56 页共 57 页

57 打开 part-r 文件, 可以看到运行结果 : 7369 and 7499 = and 7521 = and 7566 = and 7654 = and 7698 = 3... 第 57 页共 57 页

三种方法实现Hadoop(MapReduce)全局排序(1)

三种方法实现Hadoop(MapReduce)全局排序(1) 三种方法实现 Hadoop(MapReduce) 全局排序 () 三种方法实现 Hadoop(MapReduce) 全局排序 () 我们可能会有些需求要求 MapReduce 的输出全局有序, 这里说的有序是指 Key 全局有序 但是我们知道,MapReduce 默认只是保证同一个分区内的 Key 是有序的, 但是不保证全局有序 基于此, 本文提供三种方法来对 MapReduce 的输出进行全局排序

More information

雲端 Cloud Computing 技術指南 運算 應用 平台與架構 10/04/15 11:55:46 INFO 10/04/15 11:55:53 INFO 10/04/15 11:55:56 INFO 10/04/15 11:56:05 INFO 10/04/15 11:56:07 INFO

雲端 Cloud Computing 技術指南 運算 應用 平台與架構 10/04/15 11:55:46 INFO 10/04/15 11:55:53 INFO 10/04/15 11:55:56 INFO 10/04/15 11:56:05 INFO 10/04/15 11:56:07 INFO CHAPTER 使用 Hadoop 打造自己的雲 8 8.3 測試 Hadoop 雲端系統 4 Nodes Hadoop Map Reduce Hadoop WordCount 4 Nodes Hadoop Map/Reduce $HADOOP_HOME /home/ hadoop/hadoop-0.20.2 wordcount echo $ mkdir wordcount $ cd wordcount

More information

使用MapReduce读取XML文件

使用MapReduce读取XML文件 使用 MapReduce 读取 XML 文件 XML( 可扩展标记语言, 英语 :extensible Markup Language, 简称 : XML) 是一种标记语言, 也是行业标准数据交换交换格式, 它很适合在系统之间进行数据存储和交换 ( 话说 Hadoop H ive 等的配置文件就是 XML 格式的 ) 本文将介绍如何使用 MapReduce 来读取 XML 文件 但是 Had oop

More information

三种方法实现Hadoop(MapReduce)全局排序(2)

三种方法实现Hadoop(MapReduce)全局排序(2) 三种方法实现 Hadoop(MapReduce) 全局排序 (2) 我在前面的文章介绍了 MapReduce 中两种全排序的方法及其实现 但是上面的两种方法都是有很大的局限性 : 方法一在数据量很大的时候会出现 OOM 问题 ; 方法二虽然能够将数据分散到多个 Reduce 中, 但是问题也很明显 : 我们必须手动地找到各个 Reduce 的分界点, 尽量使得分散到每个 Reduce 的数据量均衡

More information

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 odps-sdk 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基 开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些

More information

目录 1 本期内容 MapReduce 理论简介 MapReduce 编程模型 MapReduce 处理过程 运行 WordCount 程序 准备工作 运行例子

目录 1 本期内容 MapReduce 理论简介 MapReduce 编程模型 MapReduce 处理过程 运行 WordCount 程序 准备工作 运行例子 细细品味 Hadoop Hadoop 集群 ( 第 6 期 ) 精华集锦 csaxp http://www.xiapistudio.com/ 2012 年 3 月 1 日 目录 1 本期内容... 2 1.1 MapReduce 理论简介... 2 1.1.1 MapReduce 编程模型... 2 1.1.2 MapReduce 处理过程... 2 1.2 运行 WordCount 程序... 3

More information

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6:

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6: Chapter 15. Suppressed Exception CH14 Finally Block Java SE 7 try-with-resources JVM cleanup try-with-resources JVM cleanup cleanup Java SE 7 Throwable getsuppressed Throwable[] getsuppressed() Suppressed

More information

MapReduce

MapReduce MapReduce 陳威宇 Review Hadoop Hdfs Datanode Namenode files / blocks Data locality ( 在地運算 ) 2 Outline What is MapReduce Process flow Yarn Configuration Java programing 3 MapReduce Introduction Objective :

More information

前 言

前    言 分布式计算框架 MapReduce 本章重点 : MapReduce 编程模型 使用 MapReduce 开发常用的功能 本章目标 : 了解 MapReduce 是什么掌握 MapReduce 编程模型掌握 MapReduce 中常见核心 API 的编程掌握使用 MapReduce 开发常用的功能 Hadoop&Spark 大数据开发实战 本章任务 学习本章, 需要完成以下 个工作任务 请记录下来学习过程中所遇到的问题,

More information

Microsoft PowerPoint - hbase_program(0201).ppt

Microsoft PowerPoint - hbase_program(0201).ppt TSMC 教育訓練課程 HBase Programming < V 0.20 > 王耀聰陳威宇 [email protected] [email protected] Outline HBase 程式編譯方法 HBase 程式設計 常用的 HBase API 說明實做 I/O 操作搭配 Map Reduce 運算 其他用法補充 其他專案 2 HBase 程式編譯方法 此篇介紹兩種編譯與執行 HBase

More information

chp6.ppt

chp6.ppt Java 软 件 设 计 基 础 6. 异 常 处 理 编 程 时 会 遇 到 如 下 三 种 错 误 : 语 法 错 误 (syntax error) 没 有 遵 循 语 言 的 规 则, 出 现 语 法 格 式 上 的 错 误, 可 被 编 译 器 发 现 并 易 于 纠 正 ; 逻 辑 错 误 (logic error) 即 我 们 常 说 的 bug, 意 指 编 写 的 代 码 在 执 行

More information

JavaIO.PDF

JavaIO.PDF O u t p u t S t ream j a v a. i o. O u t p u t S t r e a m w r i t e () f l u s h () c l o s e () public abstract void write(int b) throws IOException public void write(byte[] data) throws IOException

More information

《大话设计模式》第一章

《大话设计模式》第一章 第 1 章 代 码 无 错 就 是 优? 简 单 工 厂 模 式 1.1 面 试 受 挫 小 菜 今 年 计 算 机 专 业 大 四 了, 学 了 不 少 软 件 开 发 方 面 的 东 西, 也 学 着 编 了 些 小 程 序, 踌 躇 满 志, 一 心 要 找 一 个 好 单 位 当 投 递 了 无 数 份 简 历 后, 终 于 收 到 了 一 个 单 位 的 面 试 通 知, 小 菜 欣 喜

More information

EJB-Programming-4-cn.doc

EJB-Programming-4-cn.doc EJB (4) : (Entity Bean Value Object ) JBuilder EJB 2.x CMP EJB Relationships JBuilder EJB Test Client EJB EJB Seminar CMP Entity Beans Session Bean J2EE Session Façade Design Pattern Session Bean Session

More information

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6 www.brainysoft.net 1.JasperReport ireport...4 1.1 JasperReport...4 1.2 ireport...4 2....4 2.1 JDK...4 2.1.1 JDK...4 2.1.2 JDK...5 2.1.3 JDK...5 2.2 ant...6 2.2.1 ant...6 2.2.2 ant...6 2.3 JasperReport...7

More information

Mac Java import com.apple.mrj.*;... public class MyFirstApp extends JFrame implements ActionListener, MRJAboutHandler, MRJQuitHandler {... public MyFirstApp() {... MRJApplicationUtils.registerAboutHandler(this);

More information

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit Tomcat Web JUnit Cactus JUnit Java Cactus JUnit 26.1 JUnit Java JUnit JUnit Java JSP Servlet JUnit Java Erich Gamma Kent Beck xunit JUnit boolean JUnit Java JUnit Java JUnit Java 26.1.1 JUnit JUnit How

More information

Microsoft Word - 01.DOC

Microsoft Word - 01.DOC 第 1 章 JavaScript 简 介 JavaScript 是 NetScape 公 司 为 Navigator 浏 览 器 开 发 的, 是 写 在 HTML 文 件 中 的 一 种 脚 本 语 言, 能 实 现 网 页 内 容 的 交 互 显 示 当 用 户 在 客 户 端 显 示 该 网 页 时, 浏 览 器 就 会 执 行 JavaScript 程 序, 用 户 通 过 交 互 式 的

More information

untitled

untitled 1 Outline 數 料 數 數 列 亂數 練 數 數 數 來 數 數 來 數 料 利 料 來 數 A-Z a-z _ () 不 數 0-9 數 不 數 SCHOOL School school 數 讀 school_name schoolname 易 不 C# my name 7_eleven B&Q new C# (1) public protected private params override

More information

操作指南产品文档

操作指南产品文档 云数据库 Hbase 操作指南 产品文档 版权声明 2015-2016 腾讯云版权所有 本文档著作权归腾讯云单独所有, 未经腾讯云事先书面许可, 任何主体不得以任何形式复制 修改 抄袭 传 播全部或部分本文档内容 商标声明 及其它腾讯云服务相关的商标均为腾讯云计算 ( 北京 ) 有限责任公司及其关联公司所有 本文档涉及的第三方 主体的商标, 依法由权利人所有 服务声明 本文档意在向客户介绍腾讯云全部或部分产品

More information

Hadoop 集群 ( 第 9 期 ) MapReduce 初级案例 1 数据去重 数据去重 主要是为了掌握和利用并行化思想来对数据进行有意义的筛选 统计大 数据集上的数据种类个数 从网站日志中计算访问地等这些看似庞杂的任务都会涉及数据 去重 下面就进入这个实例的 MapReduce 程序设计 1.

Hadoop 集群 ( 第 9 期 ) MapReduce 初级案例 1 数据去重 数据去重 主要是为了掌握和利用并行化思想来对数据进行有意义的筛选 统计大 数据集上的数据种类个数 从网站日志中计算访问地等这些看似庞杂的任务都会涉及数据 去重 下面就进入这个实例的 MapReduce 程序设计 1. 细细品味 Hadoop Hadoop 集群 ( 第 9 期 ) 精华集锦 csaxp 虾皮工作室 http://www.cnblogs.com/xia520pi/ 2012 年 6 月 4 日 Hadoop 集群 ( 第 9 期 ) MapReduce 初级案例 1 数据去重 数据去重 主要是为了掌握和利用并行化思想来对数据进行有意义的筛选 统计大 数据集上的数据种类个数 从网站日志中计算访问地等这些看似庞杂的任务都会涉及数据

More information

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0,

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0, http://debut.cis.nctu.edu.tw/~chi Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0, : POSITIVE_INFINITY NEGATIVE_INFINITY

More information

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入 100 年 特 種 考 試 地 方 政 府 公 務 人 員 考 試 試 題 等 別 : 三 等 考 試 類 科 : 資 訊 處 理 科 目 : 系 統 分 析 與 設 計 一 請 參 考 下 列 旅 館 管 理 系 統 的 使 用 案 例 圖 (Use Case Diagram) 撰 寫 預 約 房 間 的 使 用 案 例 規 格 書 (Use Case Specification), 繪 出 入

More information

Guava学习之Resources

Guava学习之Resources Resources 提供提供操作 classpath 路径下所有资源的方法 除非另有说明, 否则类中所有方法的参数都不能为 null 虽然有些方法的参数是 URL 类型的, 但是这些方法实现通常不是以 HTTP 完成的 ; 同时这些资源也非 classpath 路径下的 下面两个函数都是根据资源的名称得到其绝对路径, 从函数里面可以看出,Resources 类中的 getresource 函数都是基于

More information

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌 语 言 程 序 设 计 郑 莉 胡 家 威 编 著 清 华 大 学 逸 夫 图 书 馆 北 京 内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌 握 语

More information

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii 前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii C# 7 More Effective C# C# C# C# C# C# Common Language Runtime CLR just-in-time

More information

1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10

1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10 Java V1.0.1 2007 4 10 1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10 6.2.10 6.3..10 6.4 11 7.12 7.1

More information

<4D6963726F736F667420506F776572506F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

<4D6963726F736F667420506F776572506F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074> 程 序 设 计 实 习 INFO130048 3-2.C++ 面 向 对 象 程 序 设 计 重 载 继 承 多 态 和 聚 合 复 旦 大 学 计 算 机 科 学 与 工 程 系 彭 鑫 [email protected] 内 容 摘 要 方 法 重 载 类 的 继 承 对 象 引 用 和 拷 贝 构 造 函 数 虚 函 数 和 多 态 性 类 的 聚 集 复 旦 大 学 计 算 机 科 学

More information

java2d-4.PDF

java2d-4.PDF 75 7 6 G r a d i e n t P a i n t B a s i c S t r o k e s e t P a i n t ( ) s e t S t o r k e ( ) import java.awt.*; import java.awt.geom.*; public class PaintingAndStroking extends ApplicationFrame { public

More information

Hive:用Java代码通过JDBC连接Hiveserver

Hive:用Java代码通过JDBC连接Hiveserver Hive: 用 Java 代码通过 JDBC 连接 Hiveserver 我们可以通过 CLI Client Web UI 等 Hive 提供的用户接口来和 Hive 通信, 但这三种方式最常用的是 CLI;Client 是 Hive 的客户端, 用户连接至 Hive Server 在启动 Client 模式的时候, 需要指出 Hive Server 所在节点, 并且在该节点启动 Hive Server

More information

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 -> 目录 1 大概思路... 1 2 创建 WebAPI... 1 3 创建 CrossMainController 并编写... 1 4 Nuget 安装 microsoft.aspnet.webapi.cors... 4 5 跨域设置路由... 4 6 编写 Jquery EasyUI 界面... 5 7 运行效果... 7 8 总结... 7 1 1 大概思路 创建 WebAPI 创建 CrossMainController

More information

Learning Java

Learning Java Java Introduction to Java Programming (Third Edition) Prentice-Hall,Inc. Y.Daniel Liang 2001 Java 2002.2 Java2 2001.10 Java2 Philip Heller & Simon Roberts 1999.4 Java2 2001.3 Java2 21 2002.4 Java UML 2002.10

More information

通过Hive将数据写入到ElasticSearch

通过Hive将数据写入到ElasticSearch 我在 使用 Hive 读取 ElasticSearch 中的数据 文章中介绍了如何使用 Hive 读取 ElasticSearch 中的数据, 本文将接着上文继续介绍如何使用 Hive 将数据写入到 ElasticSearch 中 在使用前同样需要加入 elasticsearch-hadoop-2.3.4.jar 依赖, 具体请参见前文介绍 我们先在 Hive 里面建个名为 iteblog 的表,

More information

用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應

用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應 專題進度 老師 : 趙啟時老師 學生 : 陳建廷 2013/10/13 用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應 程式碼 : package com.example.phone; import java.util.arraylist;

More information

输入 project name 选择完成

输入 project name 选择完成 JAVA 程序访问 HighGo DB 的环境准备 山东瀚高科技有限公司版权所有仅允许不作任何修改的转载和转发 Hibernate 的配置 MyEclipse 中创建新项目 : 选择菜单栏 file---new---project 选择 web project 进行下一步 输入 project name 选择完成 4. 单击 " 添加 JAR/ 文件夹 ", 会如下图出现 JDBC 下载 Hibernate

More information

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

KillTest 质量更高 服务更好 学习资料   半年免费更新服务 KillTest 质量更高 服务更好 学习资料 http://www.killtest.cn 半年免费更新服务 Exam : 1Z0-854 Title : Java Standard Edition 5 Programmer Certified Professional Upgrade Exam Version : Demo 1 / 12 1.Given: 20. public class CreditCard

More information

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 复习 Java 包 创建包 : package 语句, 包结构与目录结构一致 使用包 : import restaurant/ - people/ - Cook.class - Waiter.class - tools/ - Fork.class

More information

北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 前 言 吾 尝 终 日 而 思 矣, 不 如 须 臾 之 所 学 也 ; 吾 尝 跂 而 望 矣, 不 如 登 高 之 博 见 也 登 高 而 招, 臂 非 加 长 也, 而 见

北 风 网 讲 师 原 创 作 品 ---- 仅 供  学 员 内 部 交 流 使 用 前 言 吾 尝 终 日 而 思 矣, 不 如 须 臾 之 所 学 也 ; 吾 尝 跂 而 望 矣, 不 如 登 高 之 博 见 也 登 高 而 招, 臂 非 加 长 也, 而 见 北 风 网 讲 师 原 创 作 品 ---- 仅 供 www.ibeifeng.com 学 员 内 部 交 流 使 用 前 言 吾 尝 终 日 而 思 矣, 不 如 须 臾 之 所 学 也 ; 吾 尝 跂 而 望 矣, 不 如 登 高 之 博 见 也 登 高 而 招, 臂 非 加 长 也, 而 见 者 远 ; 顺 风 而 呼, 声 非 加 疾 也, 而 闻 者 彰 假 舆 马 者, 非 利 足 也,

More information

目 录 / CATALOG 一 桌 面 网 站 接 入 1. JAVASCRIPT 网 页 插 件 接 入 2. JS 代 码 操 作 指 引 3. 网 页 链 接 独 立 页 面 接 入 4. 网 页 链 接 接 入 操 作 指 引 5. 自 定 义 桌 面 网 站 接 入 图 标 颜 色 等 0

目 录 / CATALOG 一 桌 面 网 站 接 入 1. JAVASCRIPT 网 页 插 件 接 入 2. JS 代 码 操 作 指 引 3. 网 页 链 接 独 立 页 面 接 入 4. 网 页 链 接 接 入 操 作 指 引 5. 自 定 义 桌 面 网 站 接 入 图 标 颜 色 等 0 爱 客 服 快 速 接 入 指 南 400 005 0025 / [email protected] 目 录 / CATALOG 一 桌 面 网 站 接 入 1. JAVASCRIPT 网 页 插 件 接 入 2. JS 代 码 操 作 指 引 3. 网 页 链 接 独 立 页 面 接 入 4. 网 页 链 接 接 入 操 作 指 引 5. 自 定 义 桌 面 网 站 接 入 图 标 颜 色 等 01

More information

普通高級中學課程

普通高級中學課程 普 通 高 級 中 學 課 程 全 民 國 防 教 育 學 科 中 心 學 校 104 年 度 工 作 計 畫 主 持 人 : 呂 淑 美 校 長 指 導 單 位 教 育 部 及 教 育 部 國 民 及 學 前 教 育 署 執 行 單 位 國 立 新 竹 女 子 高 級 中 學 執 行 期 間 104 年 1 月 1 日 至 104 年 12 月 31 日 目 錄 第 一 章 前 言 V-1 壹 計

More information

Linux服务器构建与运维管理

Linux服务器构建与运维管理 1 Linux 服务器构建与运维管理 第 2 章 :Linux 基本命令 阮晓龙 13938213680 / [email protected] http://linux.xg.hactcm.edu.cn http://www.51xueweb.cn 河南中医药大学管理科学与工程学科 2018.3 2 提纲 目录与文件的操作 mkdir touch mv cp rm rmdir file tree

More information

chap07.key

chap07.key #include void two(); void three(); int main() printf("i'm in main.\n"); two(); return 0; void two() printf("i'm in two.\n"); three(); void three() printf("i'm in three.\n"); void, int 标识符逗号分隔,

More information

RxJava

RxJava RxJava By 侦跃 & @hi 头 hi RxJava 扩展的观察者模式 处 观察者模式 Observable 发出事件 Subscriber 订阅事件 bus.post(new AnswerEvent(42)); @Subscribe public void onanswer(answerevent event) {! }! Observable observable = Observable.create(new

More information

预览图 : (2) 在 SelectCity.java 中增加控件, 用于绑定 select_city 文件的 ListView, TextView,EditTest 等控件 代码和注释如下 :

预览图 : (2) 在 SelectCity.java 中增加控件, 用于绑定 select_city 文件的 ListView, TextView,EditTest 等控件 代码和注释如下 : EditText 实现城市搜索 1801210778 邹宇航 摘要 : 使用 EditText 实现搜索城市的功能, 以此为依据更新 ListView 1. 效果图 : 2. 主要步骤 (1) 在 select-city.xml 布局文件中中添加 EditText 控件用作搜索框, 然后添加 ListView 控件用来显示城市名字内容 代码如下 : 预览图 : (2) 在 SelectCity.java

More information

主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new

主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new ListView 自訂排版 主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new int[]{r.drawable.dog1, R.drawable.dog2,

More information

1. 访 问 最 新 发 行 公 告 信 息 jconnect for JDBC 7.0 1. 访 问 最 新 发 行 公 告 信 息 最 新 版 本 的 发 行 公 告 可 以 从 网 上 获 得 若 要 查 找 在 本 产 品 发 布 后 增 加 的 重 要 产 品 或 文 档 信 息, 请 访

1. 访 问 最 新 发 行 公 告 信 息 jconnect for JDBC 7.0 1. 访 问 最 新 发 行 公 告 信 息 最 新 版 本 的 发 行 公 告 可 以 从 网 上 获 得 若 要 查 找 在 本 产 品 发 布 后 增 加 的 重 要 产 品 或 文 档 信 息, 请 访 发 行 公 告 jconnect for JDBC 7.0 文 档 ID:DC74874-01-0700-01 最 后 修 订 日 期 :2010 年 3 月 2 日 主 题 页 码 1. 访 问 最 新 发 行 公 告 信 息 2 2. 产 品 摘 要 2 3. 特 殊 安 装 说 明 2 3.1 查 看 您 的 jconnect 版 本 3 4. 特 殊 升 级 指 导 3 4.1 迁 移 3

More information

Chapter 9: Objects and Classes

Chapter 9: Objects and Classes Fortran Algol Pascal Modula-2 BCPL C Simula SmallTalk C++ Ada Java C# C Fortran 5.1 message A B 5.2 1 class Vehicle subclass Car object mycar public class Vehicle extends Object{ public int WheelNum

More information

软件工程文档编制

软件工程文档编制 实训抽象类 一 实训目标 掌握抽象类的定义 使用 掌握运行时多态 二 知识点 抽象类的语法格式如下 : public abstract class ClassName abstract void 方法名称 ( 参数 ); // 非抽象方法的实现代码 在使用抽象类时需要注意如下几点 : 1 抽象类不能被实例化, 实例化的工作应该交由它的子类来完成 2 抽象方法必须由子类来进行重写 3 只要包含一个抽象方法的抽象类,

More information

FileMaker 16 ODBC 和 JDBC 指南

FileMaker 16 ODBC 和 JDBC 指南 FileMaker 16 ODBC JDBC 2004-2017 FileMaker, Inc. FileMaker, Inc. 5201 Patrick Henry Drive Santa Clara, California 95054 FileMaker FileMaker Go FileMaker, Inc. FileMaker WebDirect FileMaker Cloud FileMaker,

More information

Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7.

Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7. Kubernetes 包管理理 工具 Helm 蔺礼强 Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7. Kubernetes

More information

无类继承.key

无类继承.key 无类继承 JavaScript 面向对象的根基 周爱 民 / aimingoo [email protected] https://aimingoo.github.io https://github.com/aimingoo rand = new Person("Rand McKinnon",... https://docs.oracle.com/cd/e19957-01/816-6408-10/object.htm#1193255

More information

<4D6963726F736F667420576F7264202D20C8EDC9E82DCFC2CEE7CCE22D3039C9CF>

<4D6963726F736F667420576F7264202D20C8EDC9E82DCFC2CEE7CCE22D3039C9CF> 全 国 计 算 机 技 术 与 软 件 专 业 技 术 资 格 ( 水 平 考 试 2009 年 上 半 年 软 件 设 计 师 下 午 试 卷 ( 考 试 时 间 14:00~16:30 共 150 分 钟 请 按 下 述 要 求 正 确 填 写 答 题 纸 1. 在 答 题 纸 的 指 定 位 置 填 写 你 所 在 的 省 自 治 区 直 辖 市 计 划 单 列 市 的 名 称 2. 在 答

More information

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d =

More information

javaexample-02.pdf

javaexample-02.pdf n e w. s t a t i c s t a t i c 3 1 3 2 p u b l i c p r i v a t e p r o t e c t e d j a v a. l a n g. O b j e c t O b j e c t Rect R e c t x 1 y 1 x 2 y 2 R e c t t o S t r i n g ( ) j a v a. l a n g. O

More information

HBase 中加盐(Salting)之后的表如何读取:协处理器篇

HBase 中加盐(Salting)之后的表如何读取:协处理器篇 在 HBase Rowkey 设计指南 文章中, 我们介绍了避免数据热点的三种比较常见方法 : 加盐 - Salting 哈希 - Hashing 反转 - Reversing 其中在加盐 (Salting) 的方法里面是这么描述的 : 给 Rowkey 分配一个随机前缀以使得它和之前排序不同 但是在 Rowkey 前面加了随机前缀, 那么我们怎么将这些数据读出来呢? 我将分三篇文章来介绍如何读取加盐之后的表,

More information

开放数据处理服务 ODPS 批量数据通道

开放数据处理服务 ODPS 批量数据通道 开放数据处理服务 ODPS 批量数据通道 批量数据通道 SDK 介绍 概要 ODPS Tunnel 是 ODPS 的数据通道, 用户可以通过 Tunnel 向 ODPS 中上传或者下载数据 目前 Tunnel 仅支持表 ( 不包括视图 View) 数据的上传下载 ODPS 提供的数据上传下载工具即是基于 Tunnel SDK 编写的 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk-core"

More information

Microsoft Word - 在VMWare-5.5+RedHat-9下建立本机QTopia-2.1.1虚拟平台a.doc

Microsoft Word - 在VMWare-5.5+RedHat-9下建立本机QTopia-2.1.1虚拟平台a.doc 在 VMWare-5.5+RedHat-9 下建立 本机 QTopia-2.1.1 虚拟平台 张大海 2008-5-9 一 资源下载 1. 需要以下安装包 : tmake-1.13.tar.gz qtopia-free-source-2.1.1.tar.gz qt-embedded-2.3.10-free.tar.gz qt-x11-2.3.2.tar.gz qt-x11-free-3.3.4.tar.gz

More information

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d

More information

FileMaker 15 ODBC 和 JDBC 指南

FileMaker 15 ODBC 和 JDBC 指南 FileMaker 15 ODBC JDBC 2004-2016 FileMaker, Inc. FileMaker, Inc. 5201 Patrick Henry Drive Santa Clara, California 95054 FileMaker FileMaker Go FileMaker, Inc. / FileMaker WebDirect FileMaker, Inc. FileMaker

More information

Microsoft Word - Broker.doc

Microsoft Word - Broker.doc Broker 模式 采用 broker 模式对分布式计算进行简单模拟 系统在一个进程内模拟分布式环境, 因此不涉及网络编程和进程间通信,Broker 通过本地函数调用的方式实现 request 和 response 的转发 采用 broker 模式对分布式计算进行简单的模拟, 要求如下 : 设计四个 server, 一个 server 接收两个整数, 求和并返回结果, 一个 server 接收两个整数,

More information

Flume-ng与Mysql整合开发

Flume-ng与Mysql整合开发 Flume-ng 与 Mysql 整合开发 我们知道,Flume 可以和许多的系统进行整合, 包括了 Hadoop Spark Kafka Hbase 等等 ; 当然, 强悍的 Flume 也是可以和 Mysql 进行整合, 将分析好的日志存储到 Mysql( 当然, 你也可以存放到 pg oracle 等等关系型数据库 ) 不过我这里想多说一些 :Flume 是分布式收集日志的系统 ; 既然都分布式了,

More information

Swing-02.pdf

Swing-02.pdf 2 J B u t t o n J T e x t F i e l d J L i s t B u t t o n T e x t F i e l d L i s t J F r a m e 21 2 2 Swing C a n v a s C o m p o n e n t J B u t t o n AWT // ToolbarFrame1.java // java.awt.button //

More information

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat 本章学习目标 小风 Java 实战系列教程 AOP 思想概述 AOP 底层技术实现 AOP 术语介绍 SpringAOP 的 XML 方式 HelloWorld SpringAOP 的 XML 方式配置细节 SpringAOP 的注解方式 SpringAOP 的零配置方式 1. AOP 思想概述 1.1. AOP 思想简介 1.2. AOP 的作用 2. AOP 底层技术实现 小风 Java 实战系列教程

More information

客户端虚拟机使用说明

客户端虚拟机使用说明 Spark 客户端云主机使用手册 更新时间 2016-05-13 目录 1 集群和客户端云主机信息... 3 2 配置主机名解析... 4 3 HDFS 测试... 4 3.1 配置客户端... 4 3.2 查询 HDFS 集群信息... 4 3.3 HDFS 文件和目录操作示例... 5 4 Spark 测试... 6 4.1 启动 spark-shell... 6 4.2 示例 :Pi 估值...

More information

目 录 1 不 断 开 发 工 具 以 管 理 大 数 据...2 1.1 Hadoop* 简 介 : 支 持 从 大 数 据 中 获 得 出 色 价 值 的 可 靠 框 架... 2 1.2 大 数 据 技 术 的 行 业 生 态 系 统... 2 2 在 关 键 组 件 中 实 现 平 衡...

目 录 1 不 断 开 发 工 具 以 管 理 大 数 据...2 1.1 Hadoop* 简 介 : 支 持 从 大 数 据 中 获 得 出 色 价 值 的 可 靠 框 架... 2 1.2 大 数 据 技 术 的 行 业 生 态 系 统... 2 2 在 关 键 组 件 中 实 现 平 衡... 白 皮 书 英 特 尔 固 态 硬 盘 英 特 尔 以 太 网 融 合 网 络 英 特 尔 Hadoop* 发 行 版 软 件 应 用 大 数 据 技 术 获 得 近 实 时 分 析 巨 大 成 效 1 平 衡 的 基 础 设 施 使 工 作 负 载 完 成 时 间 从 4 小 时 缩 短 为 7 如 今, 基 于 广 泛 可 用 的 计 算 存 储 和 网 络 组 件 的 改 进, 商 业 学 术

More information

38 47995529 威 福 髮 藝 店 桃 園 市 蘆 竹 區 中 山 里 福 祿 一 街 48 號 地 下 一 樓 50,000 獨 資 李 依 純 105/04/06 府 經 登 字 第 1059003070 號 39 47995534 宏 品 餐 飲 桃 園 市 桃 園 區 信 光 里 民

38 47995529 威 福 髮 藝 店 桃 園 市 蘆 竹 區 中 山 里 福 祿 一 街 48 號 地 下 一 樓 50,000 獨 資 李 依 純 105/04/06 府 經 登 字 第 1059003070 號 39 47995534 宏 品 餐 飲 桃 園 市 桃 園 區 信 光 里 民 1 08414159 惠 鴻 眼 鏡 行 桃 園 市 中 壢 區 福 德 里 中 華 路 一 段 186 號 1 樓 30,000 獨 資 宋 耀 鴻 105/04/27 府 經 登 字 第 1059003866 號 2 17891110 承 元 冷 氣 空 調 工 程 行 桃 園 市 桃 園 區 中 德 里 國 際 路 1 段 98 巷 50 號 2 樓 之 4 200,000 獨 資 詹 安 平

More information

D getinitparameternames() 9 下 列 选 项 中, 属 于 Servlet API 中 提 供 的 request 对 象 的 包 装 类 的 是 ( ) A HttpServletRequestWrapper B HttpServletRequest C HttpServ

D getinitparameternames() 9 下 列 选 项 中, 属 于 Servlet API 中 提 供 的 request 对 象 的 包 装 类 的 是 ( ) A HttpServletRequestWrapper B HttpServletRequest C HttpServ 第 四 章 Filter( 过 滤 器 ) 样 题 A 卷 一 选 择 题 ( 每 小 题 2 分, 共 20 分 ) 1 下 面 选 项 中, 用 于 实 现 初 始 化 过 滤 器 的 方 法 是 ( ) A init(filterconfig filterconfig) B dofilter(servletrequest req,servletresponse resp,filterchain

More information