hadoop:二次排序

一、 实验目的 1. 进一步立即 MapReduce 思想 2. 编写 SecondarySort 程序。
二、 实验要求 1. 要能理解 MapReduce 编程思想 2. 会编写 MapReduce 版本二次排序程序 3. 其执行并分析执行过程。
三、 实验原理 MR 默认会对键进行排序,然而有的时候我们也有对值进行排序的需求。满足这种 需求一是可以在 reduce 阶段排序收集过来的 values,但是,如果有数量巨大的 values 可 能就会导致内存溢出等问题,这就是二次排序应用的场景——将对值的排序也安排到 MR 计算过程之中,而不是单独来做。 二次排序就是首先按照第一字段排序,然后再对第一字段相同的行按照第二字段排 序,注意不能破坏第一次排序的结果。
四、 实验步骤

新建一个IntPair类

package com.buaa;

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

import org.apache.hadoop.io.WritableComparable;

public class IntPair implements WritableComparable<IntPair>{
    private int first;
    private int second;

    public IntPair(){
    }

    public IntPair(int left, int right){
        set(left, right);
    }

    public void set(int left, int right){
        first = left;
        second = right;
    }

    @Override
    public void readFields(DataInput in) throws IOException{
        first = in.readInt();
        second = in.readInt();
    }

    @Override
    public void write(DataOutput out) throws IOException{
        out.writeInt(first);
        out.writeInt(second);
    }

    @Override
    public int compareTo(IntPair o)
    {
        if (first != o.first){
            return first < o.first ? -1 : 1;
        }else if (second != o.second){
            return second < o.second ? -1 : 1;
        }else{
            return 0;
        }
    }

    @Override
    public int hashCode(){
        return first * 157 + second;
    }

    @Override
    public boolean equals(Object right){
        if (right == null)
            return false;
        if (this == right)
            return true;
        if (right instanceof IntPair){
            IntPair r = (IntPair) right;
            return r.first == first && r.second == second;
        }else{
            return false;
        }
    }

    public int getFirst(){
        return first;
    }

    public int getSecond(){
        return second;
    }
}

新建一个SecondarySort类

package com.buaa;

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
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.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Partitioner;
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;


@SuppressWarnings("deprecation")
public class SecondarySort {
    public static class Map extends Mapper<LongWritable, Text, IntPair, IntWritable> {

        public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            String line = value.toString();
            StringTokenizer tokenizer = new StringTokenizer(line);
            int left = 0;
            int right = 0;
            if (tokenizer.hasMoreTokens()) {
                left = Integer.parseInt(tokenizer.nextToken());
                if (tokenizer.hasMoreTokens())
                    right = Integer.parseInt(tokenizer.nextToken());
                context.write(new IntPair(left, right), new IntWritable(right));
            }
        }
    }

    /*
     * 自定义分区函数类FirstPartitioner,根据 IntPair中的first实现分区
     */
    public static class FirstPartitioner extends Partitioner<IntPair, IntWritable>{
        @Override
        public int getPartition(IntPair key, IntWritable value,int numPartitions){
            return Math.abs(key.getFirst() * 127) % numPartitions;
        }
    }

    /*
     * 自定义GroupingComparator类,实现分区内的数据分组
     */
    @SuppressWarnings("rawtypes")
    public static class GroupingComparator extends WritableComparator{
        protected GroupingComparator(){
            super(IntPair.class, true);
        }

        @Override
        public int compare(WritableComparable w1, WritableComparable w2){
            IntPair ip1 = (IntPair) w1;
            IntPair ip2 = (IntPair) w2;
            int l = ip1.getFirst();
            int r = ip2.getFirst();
            return l == r ? 0 : (l < r ? -1 : 1);
        }
    }

    public static class Reduce extends Reducer<IntPair, IntWritable, Text, IntWritable> {

        public void reduce(IntPair key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
            for (IntWritable val : values) {
                context.write(new Text(Integer.toString(key.getFirst())), val);
            }
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        // 读取配置文件
        Configuration conf = new Configuration();

        // 判断路径是否存在,如果存在,则删除
        Path mypath = new Path(args[1]);
        FileSystem hdfs = mypath.getFileSystem(conf);
        if (hdfs.isDirectory(mypath)) {
            hdfs.delete(mypath, true);
        }

        Job job = new Job(conf, "secondarysort");
        // 设置主类
        job.setJarByClass(SecondarySort.class);

        // 输入路径
        FileInputFormat.setInputPaths(job, new Path(args[0]));
        // 输出路径
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        // Mapper
        job.setMapperClass(Map.class);
        // Reducer
        job.setReducerClass(Reduce.class);

        // 分区函数
        job.setPartitionerClass(FirstPartitioner.class);

        // 本示例并没有自定义SortComparator,而是使用IntPair中compareTo方法进行排序 job.setSortComparatorClass();

        // 分组函数
        job.setGroupingComparatorClass(GroupingComparator.class);

        // map输出key类型
        job.setMapOutputKeyClass(IntPair.class);
        // map输出value类型
        job.setMapOutputValueClass(IntWritable.class);

        // reduce输出key类型
        job.setOutputKeyClass(Text.class);
        // reduce输出value类型
        job.setOutputValueClass(IntWritable.class);

        // 输入格式
        job.setInputFormatClass(TextInputFormat.class);
        // 输出格式
        job.setOutputFormatClass(TextOutputFormat.class);

        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

导入lib包
步骤如下:
#导入hadoop文件夹路径下的lib包。
1.点击file>Project Structure>Modules>+号>Library下的java找到你自己的lib文件然后ok。完成后打jar包。
jar包操作如下:
在这里插入图片描述
在这里插入图片描述
勾选Include in project build 点击ok就完成了jar的打包
然后点击Build在这里插入图片描述
完成后就会出现一下jar包
在这里插入图片描述
然后将这个包用ftp上传到hadoop中
然后用

用start-all.sh启动hadoop
创建输入和输出的文件夹;
2.创建hadoop fs -mkdir -p /datas/in , hadoop fs -mkdir -p /datas/out
3创建secsortdata.txt文档
在这里插入图片描述
在这里插入图片描述
用ftp传到hadoop中。
5把上传到hadoop中的txt文档用hadoop fs -put secsortdata.txt /datas/in上传到hdfs中
6.在你java的jar包路径下执行
hadoop jar wordcount.jar /datas/in/secsortdata.txt /datas/out
在这里插入图片描述
然后用hadoop fs -cat /datas/out/part-r-00000
查看
在这里插入图片描述
这样就成功了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值