MapReduce之Map join操作

MapReduce之Map join操作(分布式缓存)

案例结合

分析手机销售量前三位的品牌,这三个品牌中每个品牌销售量前三位的型号

file:part-r-00000 (小表)

在这里插入图片描述

file:test2.txt (大表,部分数据)

Apple	 iPhone 11 Pro	9月	"'暗夜绿色', '深空灰色', '金色', '银色'"	5.8英寸	CPU型号:其他	电池不可拆卸	其他	256GB	8329.0	7600.0
Apple	 iPhone 12 Pro	10月	"'海蓝色', '石墨色', '银色', '金色'"	6.1英寸	CPU型号:其他	电池不可拆卸	其他	128GB	8879.0	3300.0
Apple	 iPhone 12 mini	以官网信息为准	"'黑色', '白色', '蓝色', '绿色', '红色'"	5.4英寸	CPU型号:其他	电池不可拆卸	其他	64GB	5566.0	30.0
Apple	Apple iPhone 11	9月	"'白色', '绿色', '红色', '紫色', '黑色', '黄色'"	6.1英寸	CPU型号:其他	电池不可拆卸	其他	其他	4458.5	47000.0
华为(HUAWEI)	 华为畅享Z 5G	5月	"'深海蓝', '幻夜黑', '樱雪晴空'"	6.5英寸	CPU型号:其他	电池不可拆卸	6GB	128GB	2599.0	400.0
华为(HUAWEI)	 华为畅享Z 5G	以官网信息为准	"'幻夜黑', '深海蓝', '樱雪晴空'"	6.5英寸	CPU型号:其他	电池不可拆卸	8GB	128GB	2499.0	7.0
华为(HUAWEI)	 华为(HUAWEI)nova6	12月	"'亮黑色', '普罗旺斯', '苏音蓝', '蜜语红·星耀版'"	6.57英寸	CPU型号:其他	电池不可拆卸	8GB	128GB	3699.0	6.0
华为(HUAWEI)	-	10月	"'天空之境', '幻夜黑', '极光蓝', '相思红'"	6.39英寸	CPU型号:其他	电池不可拆卸	其他	128GB	1399.0	3200.0
飞利浦(PHILIPS)	E102A	6月		1.8英寸	CPU型号:其他	电池可拆卸	2GB以下	8GB以下	99.0	3800.0
飞利浦(PHILIPS)	E106	1月	"'黑色', '红色'"	其他英寸	CPU型号:其他	电池可拆卸	2GB以下	8GB以下	99.0	520000.0
飞利浦(PHILIPS)	E109	10月	"'黑色', '红色', '深海蓝', 'E109C电信版黑色', 'E109C电信版红色'"	1.8英寸	CPU型号:其他	电池可拆卸	2GB以下	8GB以下	99.0	1600.0
飞利浦(PHILIPS)	E109	6月	"'深海蓝', '陨石黑', '炫酷红'"	其他英寸	CPU型号:其他	电池可拆卸	其他	其他	99.0	51000.0
飞利浦(PHILIPS)	E109C	8月	"'黑色', '红色'"	1.77英寸	CPU型号:其他	电池可拆卸	2GB以下	8GB以下	175.0	24750.0
金立(Gionee)	金立A880	以官网信息为准	"'红色', '黑色'"	2.8英寸	CPU型号:其他	电池可拆卸	2GB以下	8GB以下	268.0	400.0
金立(Gionee)	金立GN5601	3月	"'星空黑', '流沙金'"	6.21英寸	CPU型号:其他	电池不可拆卸	4GB	64GB	799.0	100.0
金立(Gionee)	金立M11s	9月	"'梦幻蓝', '墨玉绿', '黑色'"	6.3英寸	CPU型号:其他	电池不可拆卸	6GB	128GB	1099.0	200.0
金立(Gionee)	金立M30	8月		6.0英寸	CPU型号:其他	电池不可拆卸	8GB	128GB	1399.0	500.0
金立(Gionee)	金立(Gionee) K50 Pro	10月	"'冰霜银', '深海蓝', '零度白'"	6.5英寸	CPU型号:其他	电池不可拆卸	8GB	128GB	799.0	10.0
锤子(smartisan)	以官网信息为准	以官网信息为准	"'黑色', '松绿色'"	6.67英寸	CPU型号:骁龙865	电池不可拆卸	其他	其他	4799.0	20.0
锤子(smartisan)	坚果R2	10月	"'浅黑色 8GB+128GB', '浅黑色 8GB+256GB', '松绿色 8GB+256GB', '松绿色 12GB+256GB'"	6.67英寸	CPU型号:骁龙865
利用MapReduce中的setup方法与DistributedCache
  • setup()

    此方法被MapReduce框架仅且执行一次,在执行Map任务前,进行相关变量或者资源的集中初始化工作。若是将资源初始化工作放在方法map()中,导致Mapper任务在解析每一行输入时都会进行资源初始化工作,导致重复,程序运行效率不高!

  • DistributedCache(分布式缓存)

    DistributedCache有效地分发特定于应用程序的大型只读文件。DistributedCache是MapReduce框架提供的一种工具,用于缓存应用程序所需的文件(文本,档案,jars等)。

Notice:使用分布式缓存需要事先将小表存放入hdfs中

Main(主类)
package Clean_TopN_s;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class TopNMain {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException, URISyntaxException {
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);
        
        // 添加小表在hdfs的路径
        job.addCacheFile(new URI("hdfs://localhost:9090/test/part-r-00000"));
        
        job.setJarByClass(TopNMain.class);
        job.setMapperClass(TopNMapper.class);
        job.setReducerClass(TopNReducer.class);
        job.setPartitionerClass(TopNPartitioner.class);
        job.setGroupingComparatorClass(TopNGroupPartitioner.class);
        job.setMapOutputKeyClass(TopNBean.class);
        job.setMapOutputValueClass(Text.class);
        
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(NullWritable.class);

        Path in = new Path("file:///H:\\newData\\test2.txt");
        Path out = new Path("file:///H:\\newData\\map_join_out");

        FileInputFormat.addInputPath(job, in);
        FileOutputFormat.setOutputPath(job, out);
        System.exit(job.waitForCompletion(true) ? 0 : 1);


    }
}
Map(含改进前与改进后对比)
package Clean_TopN_s;

import org.apache.hadoop.fs.FSDataInputStream;
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 java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.HashMap;

public class TopNMapper extends Mapper<LongWritable, Text, TopNBean,Text> {
    private HashMap<String,String> map = new HashMap<>();
    @Override
    protected void setup(Context context) throws IOException, InterruptedException {

        // 第一件事:将分布式缓存中的小表数据读取到本地map集合中

        // 1:获取分布式缓存文件列表
        URI[] cacheFiles = context.getCacheFiles();

        // 2:获取指定的分布式缓存文件的文件系统(FileSystem)
        FileSystem fileSystem = FileSystem.get(cacheFiles[0], context.getConfiguration());

        // 3:获取文件的输入流
        FSDataInputStream inputStream = fileSystem.open(new Path(cacheFiles[0]));

        // 4:读取文件内容,并将数据存入Map集合
        //4.1 将字节输入流转为字符缓冲流FSDataInputStream----->BufferedReader
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        //4.2 读取小表文件内容,以行为单位,并将读取的数据存入map集合

        String line = null;
        while((line = bufferedReader.readLine()) != null){
            map.put(line,line);
        }

        // 5:关闭流
        bufferedReader.close();
        fileSystem.close();

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

        /**
         * 半自动,需要手动填写Top3品牌
         */
        
        /**
        // 拆分文本数据,得到城市和房价
        String [] split =  value.toString().split("\t");
        if (split[0].equals("Apple")||split[0].equals("华为(HUAWEI)")||split[0].equals("飞利浦(PHILIPS)")){
            // 封装topNBean 得到K2
            TopNBean topNBean = new TopNBean();
        //  topNBean.setH_city(split[0]);
        //  topNBean.setH_price(Integer.parseInt(split[7]));
            topNBean.setH_city(split[0]);
            topNBean.setH_price(Double.parseDouble(split[10]));

            // 将K2,V2写入上下文
            context.write(topNBean,value);
        }else {
            return;
        }
        **/
        
        /**
         * 改进后,不需要手动填写品牌
         */
        String[] split = value.toString().split("\t");
        String brandname = split[0]; // K2

        String brandLine = map.get(brandname);
        if (brandLine != null) {

            TopNBean topNBean = new TopNBean();
            topNBean.setH_city(split[0]);
            topNBean.setH_price(Double.parseDouble(split[10]));

            context.write(topNBean, new Text(value));
        }

    }
}

Partitioner(自定义分组)
package Clean_TopN_s;

import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;

// 1:继承WriteableComparator
public class TopNGroupPartitioner extends WritableComparator {
    // 2:调用父类的有参构造
    public TopNGroupPartitioner() {
        super(TopNBean.class,true);
    }

    // 3:指定分组的规则(重写方法)
    @Override
    public int compare(WritableComparable a, WritableComparable b) {
        // 3.1 对形参做强制类型转换
        TopNBean frist = (TopNBean)a;
        TopNBean second = (TopNBean)b;

        // 3.2 指定分组规则
        return frist.getH_city().compareTo(second.getH_city());
    }
}
Bean(实现组内排序)
package Clean_TopN_s;

import org.apache.hadoop.io.WritableComparable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

public class TopNBean implements WritableComparable<TopNBean> {
    private String h_city;
    private Double h_price;
    public String getH_city() {
        return h_city;
    }

    public void setH_city(String h_city) {
        this.h_city = h_city;
    }

    public Double getH_price() {
        return h_price;
    }

    public void setH_price(Double h_price) {
        this.h_price = h_price;
    }

    @Override
    public String toString() {
        return  h_city + '\t' +
                h_price ;
    }

    @Override
    public int compareTo(TopNBean topNBean) {
        int i = this.h_city.compareTo(topNBean.h_city);
        if(i == 0){
            i = this.h_price.compareTo(topNBean.h_price) * -1;
        }
        return i;
    }

    @Override
    public void write(DataOutput dataOutput) throws IOException {
        dataOutput.writeUTF(h_city);
        dataOutput.writeDouble(h_price);
    }

    @Override
    public void readFields(DataInput dataInput) throws IOException {
        this.h_city = dataInput.readUTF();
        this.h_price = dataInput.readDouble();
    }
}
Reduce(取Top3)
package Clean_TopN_s;

import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class TopNReducer extends Reducer<TopNBean, Text,Text, NullWritable> {

    @Override
    protected void reduce(TopNBean key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
        int i = 0;
        for (Text value : values) {
            context.write(value, NullWritable.get());
            i++;
            if (i >= 3){
                break;
            }
        }
    }
}
结果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值