hadoop第二篇:使用Maven开发Hadoop编程进阶

Hadoop——使用idea+maven开发Hadoop项目入门 我们这里使用windows系统作为开发系统 首先保证已在Linux中正确开启Hadoop集群,然后要在windows的环境变量里新加一个变量HADOOP_USER_NAME,值为集群里开启Hadoop服务的账户,笔者在服务器中用root用户使用的start-dfs.sh,所以这里的值为root。 然后我们将Hadoop的两个配置文件core-site.xml和hdfs-site.xml传输到win... 阅读详情

Hadoop第二篇:使用Maven开发Hadoop编程进阶

如何进行java代码开发进行符合自己需求的实践,先从Wordcount看看它是如何做的,这里从使用java接口看看一些基本的操作开始。

基础环境

  • win7
  • JDK1.8
  • maven安装
  • IDEA
  • Hadoop在centos上部署完成(单机版,请参看前一篇)

java代码

IDEA创建一个java项目

pom.xml如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bamboo</groupId>
    <artifactId>hadoop-1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.5</version>
        </dependency>

        <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.2</version>
        </dependency>
    </dependencies>

</project>

文件的创建和读取

直接本地运行即可

使用mapredace进行数据处理

代码重现wordCount的内容,这里类取名为hadoop2

MapReduce理论

这部分可以跳过直接后面的代码,然后再回过头看看。

MapReduce分成了两个部分:
      1)映射(Mapping)对集合里的每个目标应用同一个操作。如把大象放进冰箱分几个步骤,那么就可以把每个步奏当成一个mapping.
      2)化简(Reducing)遍历集合中的元素来返回一个综合的结果。即,每个步奏的输出结果的过程,这个任务属于reducing。
 
你向MapReduce框架提交一个计算作业时
1.它会首先把计算作业拆分成若干个Map任务,然后分配到不同的节点上去执行,每一个Map任务处理输入数据中的一部分
2.当Map任务完成后,它会经历Shuffle将多个map结果合并生成一些中间文件
3.这些中间文件将会作为Reduce任务的输入数据,经过Reduce处理之后把结果合并输出

Shuffle的主要目标就是把前面若干个Map的输出合并成若干个租(相当于group by)。

Reduce任务的主要目标就是把Shuffle合并后的数据作为输入数据处理后输出
   MapReduce的伟大之处就在于编程人员在不会分布式并行编程的情况下,将自己的程序运行在分布式系统上资料参考。

特性

mapreduce之mapper、reducer个数

案例讲解

在map(v1)->k2函数中,输入端v1代表的是一行数据,输出端的k2可以代表是被引用的专利,在一行数据中所有v2和引用的次数。

在reduce函数中,k2还是被引用的专利,而[v2]是一个数据集,这里是将k2相同的键的v2数据合并起来。最后输出的是自己需要的数据k3代表的是被引用的专利,v3是引用的次数。

以wordcount为例,有如下数据集2份文档
hello word
hello hadoop

处理过程如下

1.每个个文档都有一个mapping
·每读取一行就按空格分割字符串为单词,则每个单词作为key,值默认为1
2.reduce处理:
·把所有的mapping处理结果合并,如单词hello的结果是 hello,[1,1] 因为出现了两次hello,这个过程由框架自己完成 我们不用处理
.按照key遍历所有的vlue集合需要手工处理,这里把所有的1相加就是该单词出现的个数

3.把结果集合输出出来

代码

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
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.util.GenericOptionsParser;

import java.io.IOException;


/**
 * MapReduce作业:功能和wordcount一样,在运行jar时设置文件输源和结果输出源
 *
 * 补充:
 * 设置命令行参数变量来编程
   这里需要借助Hadoop中的一个类Configured、一个接口Tool、ToolRunner(主要用来运行Tool的子类也就是run方法)

 * <p>源码出自https://blog.youkuaiyun.com/yinbucheng/article/details/70243593</p>
 * 拷贝人
 */


public class Hadoop2 {

    //输入资源映射处理
    public static class MyMapper extends Mapper<Object, Text, Text, IntWritable>{

        private Text event = new Text();//字符串
        private final static IntWritable one = new IntWritable(1);//默认字符串的个数为1
        //字符串的分隔
        public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
            int idx = value.toString().indexOf(" ");//空格的位置
            if (idx > 0) {
                String e = value.toString().substring(0, idx);//
                event.set(e);
                context.write(event, one);//反正结果<e,1>
            }
        }
    }

    //对输出结果集处理
    public static class MyReducer extends Reducer<Text,IntWritable,Text,IntWritable> {
        private IntWritable result = new IntWritable();

        //把多个map中返回的<e,1>合并<key,values>即<e,[1,1,1]>后遍历
        public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
            int sum = 0;
            for (IntWritable val : values) {//遍历相同key的所有结果集,这里保存的是int计算结果和
                sum += val.get();
            }
            result.set(sum);//把结果放入int
            context.write(key, result);//注意:在map或reduce上面的打印语句是没有办法输出的,但会记录到日志文件当中。
        }
    }

    /**
     *  args 在运行jar时设置参数
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
        //如果args的参数长度小于2直接退出程序
        if (otherArgs.length < 2) {
            System.err.println("Usage: EventCount <in> <out>");
            System.exit(2);
        }

        Job job = Job.getInstance(conf, "event count");//构建作业配置job

        //设置该作业所要执行的类
        job.setJarByClass(Hadoop2.class);

        job.setMapperClass(MyMapper.class);//设置map
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        job.setCombinerClass(MyReducer.class);//设置

        //设置自定义的Reducer类以及输出时的类型
        job.setReducerClass(MyReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);


        FileInputFormat.addInputPath(job, new Path(otherArgs[0]));//设置文件输入源的路径
        FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));//设置结果输出流的路径


        System.exit(job.waitForCompletion(true) ? 0 : 1);//提交作业完成后退出
    }
}

运行代码

java项目打包

mvn package

把包上传到centos上

/mnt/hadoop

创建手工数据源

cd /mnt/hadoop/input/event
[root@localhost input]# touch evenet.log.1
[root@localhost input]# touch evenet.log.2

依次vi打开粘贴如下内容

JOB_NEW ...  
JOB_NEW ...  
JOB_FINISH ...  
JOB_NEW ...  
JOB_FINISH ...  

查看数据源,清除不需要的数据源,清空数据输出路径(第一次运行时可以跳过这一步)

hdfs dfs -ls /mnt/input
hdfs dfs -rm  /mnt/input/evenet.log*
hadoop fs -rmr  /mnt/out

数据源放入dfs

hdfs dfs -ls /mnt/input
hadoop fs -mkdir -p /mnt/input
hdfs dfs -put /mnt/hadoop/input/event/*   /mnt/input
hadoop fs -ls /mnt/input/input

运行代码

hadoop jar hadoop-1-1.0-SNAPSHOT.jar Hadoop2 /mnt/input /mnt/out

等待它执行结束,查看结果

hadoop dfs -cat /mnt/out/*
DEPRECATED: Use of this script to execute hdfs command is deprecated.
Instead use the hdfs command for it.

JOB_FINISH	4
JOB_NEW	6

MapReduce深入学习进阶样例

从上面的样例中我们了解了代码处理数据的大致过程,那么如何实现更多业务场景的数据处理呢,毕竟我们不是只做单表数据的个数统计,现实中可能会有更加复杂的运用,就像我们队数据库操作一样,单表到多表,复合统计等等,列出几个比喻的例子:

日志log如下
user.log
112 王小二
113 李小明

trade.log

10:48:20.669 INFO [pool-9-thread-1] c.z.e.a.domain.job.TransSuccessJob [TransSuccessJob.java : 42] 积分交易成功通知 notifyVo={"uid":112,"coin":"yxt","amount":10,"price":13.5555,"oPrice":13.5555,"transFee":0.2711,"oTransFee":0.2711,"tid":4339,"buy":true,"ext":"","dealTime":"2018-09-04 10:03:10"}

1.比如会查询单suer表特定几个字段的结果,单表[uid,coin,amount]统计结果,如结果要求如下
23 yxt 200 ETH 10
2.查询[uaerName,coin,amout]的统计结果,这个就是多表关联查询,如结果要求如下
李三 yxt 200 ETH 10

看上去是不是很像数据库的统计,但是这里操作的不是数据库,而是文本文件甚至流式文件,MapReduce就是要实现从分布式文件中的超大数据中处理结果。而实现的关键就在于两个实现类Mapper和Reducer

而这两个实现类都需要使用的一个地方就是MapReduce<key,value>,从上面的处理过程讲解我们知道,每一个步奏都是把数据处理成为了key,value键值输出并且作为下一个处理过程的输入,第二个处理过程接收到的依然是(key,vaule)键值对的数据类型,如何实现符合我们需要的键值类型才是整个数据处理的最重要的部分,毕竟我们不可能只处理一些基本类型的数据。

一些常见的基础类型数据对<key,value>
(Text,IntWritable)前面的wordCount就用到了,学生成绩统计也可以使用
(LongWritable,LongWritable)比如手机号的流量统计,单位是KB

MapReduce: <key,value>

MapReduce常用数据类型

ByteWritable:单字节数值
IntWritable:整型数
LongWritable:长整型数
FloatWritable:浮点数
DoubleWritable:双字节数值
BooleanWritable:标准布尔型数值
Text:使用UTF8格式存储的文本
NullWritable:当<key,value>中的key或value为空时使用

以上类型中 IntWritable LongWritable Text NullWritable DoubleWritable较为常用,实际中我们可能遇到复杂的类型,比如上面举例的user.log特定字段的统计,vule的值就不是一个基础类型,而是好几个字段的复合类型,这种情况我们该如何处理呢。

MapReduce自定义数据类型

  • key实现WritableComparable
  • value通常只需要实现Writable

关键就在这里,
key决定了是不是同一个数据,比如是不是同一个人,同一个手机号,因此Comparable的功能必须有;
value则决定了你需要处理的数据是什么格式的

案例1:手机上网流量统计

数据源:
130313143750 1238 17823 3424 2342
每个电话号码每上一次网络,就会生成一条日志数据

需求目标:
手机号码 上行数据包总数 下行数据包总数 上行总流量 下行总流量
13123412431 1238 17823 3424 2342
13622311238 17223 34214 23421 1231
13123412431 12380 1828 34 23

MapReduce设计:
** key是什么?
–电话号码
** value是什么?
–后面四个字段

Map阶段结果:
把数据分割成 key,value这里的valeu是一个对象类型

13123412431        (123,2423,3453,234)
13123412431        (789,1231,4353,234)
13123412431        (1231,231,342,23) 

Shuffle阶段的结果

    key                value list
13123412431        (123,2423,3453,234),(789,1231,4353,234),(1231,231,342,23) ...
13622311238        (1233,23,342353,23234),(78239,123231,42353,2234) ...

Reduce最终结果:

 hadoop dfs -cat /mnt/out/*
DEPRECATED: Use of this script to execute hdfs command is deprecated.
Instead use the hdfs command for it.

13123412431 1276    17846   3448    2384
13123412432 1278    17848   3450    2386
13123412433 1280    17850   3452    2388
13123412434 1282    17852   3454    2390
13123412435 1284    17854   3456    2392
13123412436 1286    17856   3458    2394
13123412437 1288    17858   3460    2396
13123412438 1290    17860   3462    2398
13123412439 1292    17862   3464    2400
13123412440 1294    17864   3466    2402
构造复合类型的数据类型
package entity;

import org.apache.hadoop.io.Writable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

public class DataTotalWritable implements Writable {

    // 上行数据包总数
    private long upPackNum ;
    // 下行数据包总数
    private long downPackNum ;
    // 上行总流量
    private long upPayLoad ;
    // 下行总流量
    private long downPayLoad ;

    public DataTotalWritable() {
    }

    public DataTotalWritable(long upPackNum, long downPackNum, long upPayLoad, long downPayLoad) {
        this.set(upPackNum, downPackNum, upPayLoad, downPayLoad);
    }

    public void set (long upPackNum, long downPackNum, long upPayLoad,long downPayLoad) {
        this.upPackNum = upPackNum;
        this.downPackNum = downPackNum;
        this.upPayLoad = upPayLoad;
        this.downPayLoad = downPayLoad;
    }

    public long getUpPackNum() {
        return upPackNum;
    }

    public void setUpPackNum(long upPackNum) {
        this.upPackNum = upPackNum;
    }

    public long getDownPackNum() {
        return downPackNum;
    }

    public void setDownPackNum(long downPackNum) {
        this.downPackNum = downPackNum;
    }

    public long getUpPayLoad() {
        return upPayLoad;
    }

    public void setUpPayLoad(long upPayLoad) {
        this.upPayLoad = upPayLoad;
    }

    public long getDownPayLoad() {
        return downPayLoad;
    }

    public void setDownPayLoad(long downPayLoad) {
        this.downPayLoad = downPayLoad;
    }

    //^为异或运算, << 带符号左移, >>带符号右移, >>> 无符号右移
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (int) (downPackNum ^ (downPackNum >>> 32));
        result = prime * result + (int) (downPayLoad ^ (downPayLoad >>> 32));
        result = prime * result + (int) (upPackNum ^ (upPackNum >>> 32));
        result = prime * result + (int) (upPayLoad ^ (upPayLoad >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        DataTotalWritable other = (DataTotalWritable) obj;
        if (downPackNum != other.downPackNum)
            return false;
        if (downPayLoad != other.downPayLoad)
            return false;
        if (upPackNum != other.upPackNum)
            return false;
        if (upPayLoad != other.upPayLoad)
            return false;
        return true;
    }

    @Override
    public String toString() {
        return upPackNum + "\t"    + downPackNum + "\t"
                + upPayLoad + "\t"    + downPayLoad ;
    }

    public void write(DataOutput out) throws IOException {
        out.writeLong(upPackNum);
        out.writeLong(downPackNum);
        out.writeLong(upPayLoad);
        out.writeLong(downPayLoad);
    }

    public void readFields(DataInput in) throws IOException {
        this.upPackNum = in.readLong() ;
        this.downPackNum = in.readLong() ;
        this.upPayLoad = in.readLong() ;
        this.downPayLoad = in.readLong() ;
    }

}
map实现类和Reduce实现类
import java.io.IOException;

import entity.DataTotalWritable;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.Job;
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;

import java.io.IOException;


/**
 * MapReduce复核类型数据处理
 *
  * <p>源码出自https://blog.youkuaiyun.com/helpless_pain/article/details/7015383</p>
 * 拷贝人 bamoboo
 * 2018-9-14
 */

public class Hadoop3  extends Configured implements Tool {

    //输入资源映射处理
    public static class DataTotalMapper extends
            Mapper<LongWritable, Text, Text, DataTotalWritable> {

        @Override
        protected void map(LongWritable key, Text value, Context context)
                throws IOException, InterruptedException {

            //split by '\t'
            String[] splits = value.toString().split("\t") ;

            //以手机号码作为output key
            String phoneNum = splits[0];
            Text mapOutputKey = new Text();
            mapOutputKey.set(phoneNum);

            // set map output value
            long upPackNum = Long.parseLong(splits[1]) ;
            long downPackNum = Long.parseLong(splits[2]) ;
            long upPayLoad = Long.parseLong(splits[3]) ;
            long downPayLoad = Long.parseLong(splits[4]) ;
            DataTotalWritable mapOutputValue = new DataTotalWritable() ;
            mapOutputValue.set(upPackNum, downPackNum, upPayLoad, downPayLoad);

            //map output
            context.write(mapOutputKey, mapOutputValue);
        }
    }

    public static class DataTotalReducer extends
            Reducer<Text, DataTotalWritable, Text, DataTotalWritable> {

        @Override
        protected void reduce(Text key, Iterable<DataTotalWritable> values,
                              Context context) throws IOException, InterruptedException {

            long upPackNumSum = 0;
            long downPackNumSum = 0;
            long upPayLoadSum = 0;
            long downPayLoadSum = 0;

            //iterator
            for(DataTotalWritable value : values){
                upPackNumSum += value.getUpPackNum() ;
                downPackNumSum += value.getDownPackNum() ;
                upPayLoadSum += value.getUpPayLoad() ;
                downPayLoadSum += value.getDownPayLoad()  ;
            }

            // set output value
            DataTotalWritable outputValue = new DataTotalWritable() ;
            outputValue.set(upPackNumSum, downPackNumSum, upPayLoadSum, downPayLoadSum);

            // output
            context.write(key, outputValue);
        }
    }

    public int run(String[] args) throws Exception {

        //Job
        Configuration conf = super.getConf();
        Job job = Job.getInstance(conf);
        job.setJarByClass(getClass());

        //Mapper
        job.setMapperClass(DataTotalMapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(DataTotalWritable.class);

        //Reducer
        job.setReducerClass(DataTotalReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(DataTotalWritable.class);

        //输入路径
        Path inPath = new Path(args[0]);
        FileInputFormat.addInputPath(job, inPath);
        //输出路径
        Path outPath = new Path(args[1]);
        FileSystem dfs = FileSystem.get(conf);
        if (dfs.exists(outPath)) {
            dfs.delete(outPath, true);
        }
        FileOutputFormat.setOutputPath(job, outPath);

        //Submit Job
        boolean isSuccess = job.waitForCompletion(true);
        return isSuccess ? 0 : 1;
    }


    //这里的运行输入和输出已经在程序中写死了不需要在执行时指定参数
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();


        //运行时设置输入 输出
        String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
        //如果args的参数长度小于2直接退出程序
        if (otherArgs.length < 2) {
            System.err.println("Usage: EventCount <in> <out>");
            System.exit(2);
        }

        //也可以直接写死
        //args = new String[] {"hdfs://blue01.mydomain:8020/input2", "hdfs://blue01.mydomain:8020/output2"};

        // run job
        int status = ToolRunner.run(conf,new Hadoop3(),args);

        System.exit(status);

       /* Long p=13123412431L;
        for (int i=0;i<10;i++){
            System.out.printf("%d\t%d\t%d\t%d\t%d\n",p++ ,38+i, 23+i,  24+i, 42+i);
        }*/
    }
}

运行数据

把程序中/resources下的phone.log.1,phone.log.1上传到/mnt/hadoop/input/phone/文件夹下

把打包后的程序hadoop-1-1.0-SNAPSHOT.jar上传到/mnt/hadoop路径下

清空数据源和结果集输出源

hdfs dfs -rm  /mnt/input/*
hadoop fs -rmr  /mnt/out

数据提交到HDFS

hdfs dfs -put /mnt/hadoop/input/phone/*   /mnt/input
hdfs dfs -ls /mnt/input

运行程序并查看结果集

hadoop jar hadoop-1-1.0-SNAPSHOT.jar Hadoop3 /mnt/input /mnt/out
hadoop dfs -cat /mnt/out/*

结果就和上面中的结果集一模一样

多类型数据行转列

数据文件:
customer文件
用户CID,用户姓名,联系方式
1,Stephanie Leung,555-555-5555
2,Edward Kim,123-456-7890
3,Jose Madriz,281-330-8004
4,David Stork,408-555-0000

order文件
用户CID,订单号,价格,日期
3,A,12.95,02-Jun-2008
1,B,88.25,20-May-2008
2,C,32.00,30-Nov-2007
3,D,25.02,22-Jan-2009

目标:
用户CID,订单号,价格,时间,用户姓名,联系方式
1,B,88.25,20-May-2008,Stephanie Leung,555-555-5555
2,C,32.00,30-Nov-2007,Edward Kim,123-456-7890
3,D,25.02,22-Jan-2009,Jose Madriz,281-330-8004
3,A,12.95,02-Jun-2008,Jose Madriz,281-330-8004

思路:
选用: Join

map阶段:
** map task依次读取两个文件,切割,并设置key和value,取cid为key,同时给来自不同的文件的value打一个标签
value == flag + value

key                value list
3        customer('Jose Madriz,281-330-8004')
3       order('A,12.95,02-Jun-2008')
3       order('D,25.02,22-Jan-2009')

Shuffle阶段:

key                value list
3        customer('Jose Madriz,281-330-8004'),order('A,12.95,02-Jun-2008'),order('D,25.02,22-Jan-2009')

reduce阶段:
** Join 数据根据flag得不同摆放好次序合并
3 A,12.95,02-Jun-2008,Jose Madriz,281-330-8004
3 D,25.02,22-Jan-2009,Jose Madriz,281-330-8004

数据类型DataJoinWritable

 private String flag;
 private String data;
  public void set(String flag, String data) {
        this.flag = flag;
        this.data = data;
    }

数据拆分合并DataJoinMapper
1.按空格或者tab切割
2.splits.length长度不同则设置不同的flag
key,value存放格式为cid,(str1+str2)+str3的方式字符串拼接

     public static class DataJoinMapper extends
            Mapper<LongWritable, Text, Text, DataJoinWritable> {

        @Override
        protected void map(LongWritable key, Text value, Context context)
                throws IOException, InterruptedException {

            String[] splits = value.toString().split(",");

            //output key,以连接值为key
            String cid = splits[0];
            Text mapOutputKey = new Text();
            mapOutputKey.set(cid);

            //output value
            DataJoinWritable mapOutputValue = new DataJoinWritable();

            // length == 3 ==> customer
            if (splits.length == 3) {
                String name = splits[1];
                String phoneNum = splits[2];
                mapOutputValue.set("customer", name + "," + phoneNum);
            }

            // length == 4 ==> order
            if (splits.length == 4) {
                String name = splits[1];
                String price = splits[2];
                String date = splits[3];
                mapOutputValue.set("order", name + "," + price + "," + date);
            }
            
            context.write(mapOutputKey, mapOutputValue);
        }
    }

reduce数据在进行遍历时,由于cid相同的数据会成为一个list,根据不同的flag进行合并即可,这里customerInfo字符串 和所有OderList中的数据遍历合并,每合并一次就写出一行数据。

 public static class DataJoinReducer extends
            Reducer<Text, DataJoinWritable, NullWritable, Text> {

        @Override
        protected void reduce(Text key, Iterable<DataJoinWritable> values, Context context) 
                throws IOException, InterruptedException {

            String customerInfo = null;
            List<String> orderList = new ArrayList<String>();

            for (DataJoinWritable value : values) {
                if ("customer".equals(value.getFlag())) {
                    customerInfo = value.getData();
                } else if ("order".equals(value.getFlag())) {
                    orderList.add(value.getData());
                }
            }

            //遍历订单列表和客户信息合并为一行数据并写出
            Text outputValue = new Text();
            for (String order : orderList) {
                outputValue.set(key.toString() + "," + order + ","    + customerInfo);
                context.write(NullWritable.get(), outputValue);
            }
        }
    }

以上案例参考资料
https://blog.youkuaiyun.com/helpless_pain/article/details/70153834

参考资料

更多java HDFS操作讲解
https://www.cnblogs.com/zhangyinhua/p/7678704.html

如上代码已经上传到github,请参考我的git仓库地址
https://github.com/BambooZhang/bigData.git

Hadoop实践(二)---集群和开发环境搭建(Intellij IDEA & Maven 开发Hadoop) Intellij IDEA Maven 开发 Hadoop MapReduce 程序 阅读详情

相关推荐

Hadoop入门系列(二)idea配置hadoop开发环境

主要分两部分:一、idea配置hadoop开发环境。二、idea安装hadoop插件。一、1.为了便于各个版本的hadoop获得对应jar包以及其依赖jar包。搭建maven项目是个很好的选择。创建一个无原型的maven项目。2.在porn.xml的project内添加镜像网站和一些需要依赖的核心jar包。注意:版本号对应自己hadoop的版本号。有些通用包比如hadoop-core,在maven...

_DrZ_的博客 2万+

用Maven构建Hadoop环境

1.1用Maven创建一个标准化的Java项目 mvn archetype:generate -DgroupId=com.baidu -DartifactId=InstructionsHdfs-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false 注: DgroupId:project-packaging...

leafdown_的博客 7073

hadoop-auth

该工具包为Hadoop Auth maven依赖包,用于支持hadoop下maven项目开发

Hadoop配置Maven并使用Maven编译项目

登录虚拟机后,输入ifconfig,查看ip地址是否变化ip地址没有变化,你的xshell就可以正常连接;当然你完全可以就在虚拟机的终端操作,就不用连xshell了。

qq_54103767的博客 1183

离散数学期末考试试卷(两套)-熟悉题型

3.设集合A={a,b,c,d}上有自反关系R={,,,,},对称关系S={,,,}。6.设集合A={1,2,3},B={u,v,w},C={a,b,c},f是集合A到集合B上的映射,g是集合B到集合C上的映射,f={, , },g={},则复合函数g。5. 设集合A={a,b,c,d,e},下列选项中哪一个集合不是A的划分( )。

muse3159546973的博客 6952

RK3588嵌入式开发实战:U-Boot设备树文件修改全指南(含常见踩坑点)

本文为RK3588嵌入式开发者提供了一份详尽的U-Boot设备树文件修改实战指南。文章深入解析了设备树的核心架构,从基础硬件适配到时钟、电源管理等进阶配置,并重点总结了内存节点、串口输出、电源时序等常见踩坑点与解决方案,旨在帮助开发者高效、稳健地完成U-Boot移植与定制工作。

yhn456789的博客 729

hadoop java类型,java – 错误的值类:类org.apache.hadoop.io.Text不是类org.apache.hadoop.io.IntWritable...

我使用了一个mapper,一个reducer和一个combiner类,但是我得到的错误如下:java.io.IOException: wrong value class: class org.apache.hadoop.io.Text is not class org.apache.hadoop.io.IntWritableat org.apache.hadoop.mapred.IFile$Wri...

weixin_31210347的博客 611

【黑马-产品经理入门基础课笔记】01.认识产品经理

问题定义 ==> 可行性研究 ==> 需求分析。

2401_88466092的博客 1841

Hadoop 2.2 & HBase 0.96 Maven 依赖总结

由于Hbase 0.94对Hadoop 2.x的支持不是非常好,故直接添加Hbase 0.94的jar依赖可能会导致问题。      但是直接添加Hbase0.96的依赖,由于官方并没有发布Hbase 0.96的jar包,通过maven编译项目的时候会出现找不到jar包导致编译失败。      通过网上的资料,得知Hbase 0.94后版本,直接添加Hbase-Client的依赖,通过查询

wood_moon的专栏 5466

Open3D 可视化(1)——简单可视化【2026最新版】

简单可视化,博客长期更新,本文最新更新时间为:2026年5月10日。

点云侠的博客 5684

手把手教你学veriolg(二十六)-- Verilog CIC 滤波器设计

目录 Verilog CIC 滤波器设计1. CIC 滤波器的基本原理2. Verilog 实现3. 说明4. 测试激励5. 总结 CIC(Cascade-Integrator-Comb)滤波器是一种特殊的数字滤波器,常用于多速率信号处理中,尤其是用于信号的上采样(插值)和下采样(抽取)。CIC 滤波器的特点在于它具有简单的硬件实现、不需要乘法器(仅使用加法器和延迟元件)、且具有线性相位特性。然而,CIC 滤波器的缺点是它会产生较大的量化误差,因此在设计时需要特别注意字长的选择以避免溢出。1. CIC 滤波

MHD0815的博客 888

Qt官方MQTT库的使用

参考文档 https://www.cnblogs.com/yexiaopeng/p/8542894.html 前言 mqtt官方库不在Qt中,而是需要另外下载源码然后编译生成库,至于源码网址我没有从官方网站找到,前辈们说了下面两个网址。 github地址: https://github.com/emqtt/qmqtt https://github.com/qt/qtmqtt 我使用的是下面这个...

风尘叹 5359

YOLO26涨点改进 | 检测头Head创新改进篇 | 利用RFAConv感受野注意力卷积改进YOLO26检测头,RFAHead感受野注意力检测头,助力小目标检测高效涨点

YOLO26作为轻量化目标检测模型的新一代标杆,凭借高效的Backbone与Neck结构,在实时检测场景中表现突出,但原生检测头仍存在核心痛点——感受野固定、小目标特征感知薄弱、多尺度目标适配不足,导致在小目标密集、复杂背景遮挡等场景中漏检率偏高、定位精度不足。

qq_36130719的博客 167

Ubuntu安装Maven并且配置idea开发Hadoop3环境

文章目录前言一、下载Maven并且配置环境1.下载Maven2.配置Maven环境3.修改Maven配置二、配置idea的Hadoop开发环境1.使用本地的Maven2.配置项目总结 前言 由于Hadoop编程需要Maven项目,所以需要配置idea的环境提高Hadoop编程效率 环境:Ubuntu、Java8、idea和Hadoop3 一、下载Maven并且配置环境 1.下载Maven 到Maven官网:https://maven.apache.org/download.cgi 我这里是maven-3.

m0_46105229的博客 5187

Java 实现 MP3 音频合并工具类:摆脱 FFmpeg,高效低 CPU 的纯本地方案【需求已解决】

本方案充分发挥了 Java 音频 SPI 的潜力,实现了轻量、跨平台、低 CPU 消耗的 MP3 音频合并工具类。 对于希望在服务器或桌面应用中集成音频处理功能的开发者而言,这无疑是一个可行且优雅的解决方案。

一键难忘的博客 542

【异常】安装hermes-agent提示Git克隆仓库网络中断 fetch-pack: unexpected disconnect while reading sideband packet

本文分析了Git克隆仓库时出现网络中断错误的常见原因及解决方案。报错表现为连接被远程主机关闭、管道破裂或数据包意外终止,通常由网络不稳定、仓库过大或配置不当引起。提供了5种优先级排序的解决方法:1)使用浅克隆减少数据量;2)优化Git配置参数;3)切换网络或配置代理;4)检查SSH密钥设置;5)改用HTTPS方式克隆。特别推荐先尝试「浅克隆+HTTPS」组合方案快速验证,若问题持续再根据具体报错深入排查。文中包含详细的命令示例和配置说明,适合不同网络环境下的Git用户参考。

奶爸的编程之路,也就一周冷个三天 1418

maven引入hadoop_使用Maven搭建Hadoop开发环境

关于Maven的使用就不再啰嗦了,网上很多,并且这么多年变化也不大,这里仅介绍怎么搭建Hadoop的开发环境。1. 首先创建工程mvn archetype:generate -DgroupId=my.hadoopstudy -DartifactId=hadoopstudy -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveM...

weixin_39579468的博客 1508

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【Hadoop】:Windows下使用IDEA搭建Hadoop开发环境

笔者鼓弄了两个星期,终于把所有有关hadoop的环境配置好了,一是虚拟机上的完全分布式集群,但是为了平时写代码的方便,则在windows上也配置了hadoop的伪分布式集群,同时在IDEA上就可以编写代码,同时在windows环境下进行运行。(如果不配置windows下的伪分布式集群,则在IDEA上编写的代码无法在windows平台下运行)。笔者在网络上找了很多有关windows下使用i...

极歌科技 9934

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

maven引入hadoop_【Hadoop】使用 Maven 搭建 hadoop 开发环境

在 pom.xml 文件里添加hadoop的依赖包 hadoop-common, hadoop-client, hadoop-hdfs ,内容如下:xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">4.0.0my.hadoopstudyhadoopst...

weixin_39987211的博客 1269

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Windows下使用IDEA+Maven搭建本地Hadoop环境

IDEA结合Maven搭建本地MapReduce环境 文章目录IDEA结合Maven搭建本地MapReduce环境前言环境配置Maven新建项目初始化添加apache源添加Hadoop依赖 前言 Hadoop的开发中需要很多的依赖包,相互之间的关系较为复杂,依赖包之间复杂的关系就导致了搭建Hadoop的过程中会遇到各种报错,费心费神还调试不好,真是让人苦恼。 Maven是一个依赖管理和项目构建的工...

qq_42582489的博客 2373

Hadoop——使用idea+maven开发java-hadoop项目

第一步:打开idea,新建一个maven项目。如图 第二步:在maven的家目录选择你安装的maven的路径, User setting file路径选择所安装maven路径下 的conf目录下的setting.xml文件 然后点击Finish。 项目建立好后先不用急着操作,idea需要从仓库中下载你所需要的一些依赖jar包(前提是你的本地仓库中没有这些jar包),这需要花费一些时间。 依赖jar包下载好后会提示build success,如图: 这里我们用的jdk版本是jdk1.8,所以要将这里的

阿中丶20 4332

用maven构建hadoop项目

前言 Hadoop的MapReduce环境是一个复杂的编程环境,所以我们要尽可能地简化构建MapReduce项目的过程。Maven是一个很不错的自动化项目构建工具,通过Maven来帮助我们从复杂的环境配置中解脱出来,从而标准化开发过程。所以,写MapReduce之前,让我们先花点时间把刀磨快!!当然,除了Maven还有其他的选择Gradle(推荐), Ivy…. 后面将会有介绍几篇Ma

powerpowerxie的专栏 938

IDEA开发hadoop mapreduce 引入 Maven 依赖

<!-- hdfs程序需要引入依赖:--> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version>...

A_____lan的博客 3213

使用Maven搭建Hadoop开发环境

使用Maven搭建Hadoop开发环境

qq_44943584的博客 350

Hadoop+idea+maven开发配置

idea是java开发的利器之一,其自身集成了maven,十分适用于大型项目的开发。大多数的Hadoop程序都是在idea下开发的,本文介绍了Hadoop+idea+maven的环境配置与开发测试 准备 在ubuntu下安装Hadoop,具体细节可见之前的博客安装idea 建立项目 打开idea,选择 File---New---Project---Maven,接下来填写

u012859945的博客 5445
上一篇: Hadoop第一篇:hadoop2.7.5单机版安装
下一篇: http长连接
牧竹子
博客等级 码龄17年 572粉丝 233原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值