MapReduce 学习4 ---- 自定义分区、自定义排序、自定义组分

1. map任务处理

1.3 对输出的key、value进行分区。

分区的目的指的是把相同分类的<k,v>交给同一个reducer任务处理。

public static class MyPartitioner<Text, LongWritable> extends Partitioner<Text, LongWritable>{

		static HashMap<String,Integer> map = null;
		static{
			map = new HashMap<String,Integer>();
			map.put("gz1", 0);
			map.put("gz2", 0);
			map.put("sz1", 1);
			map.put("sz2", 1);
		}
		/**
		 * 这里是对mapper任务输出的<k2,v2>进行操作
		 * getPartition函数返回多少的值,就会有多少个reducer任务
		 *
		 * “gz1”与“gz2”的返回的都是0,所以与分发到同一个reducer任务上,但是k2的值不一样
		 * 所以分组就是
		 * <gz1,123>
		 * <gz2,234>
		 * 然后出现在不同reduce函数上
		 */
		@Override
		public int getPartition(Text key, LongWritable value, int numPartitions) {

			return (Integer)map.get(key.toString()).intValue();
		}

}

//设置分区        wcjob.setPartitionerClass(MyPartitioner.class);

自定义排序,排序是根据k2来进行排序的,k2就需要自己进行自定义类型

 private static class MyNewKey implements WritableComparable<MyNewKey> {
        long firstNum;
        long secondNum;

        public MyNewKey() {
        }

        public MyNewKey(long first, long second) {
            firstNum = first;
            secondNum = second;
        }

        @Override
        public void write(DataOutput out) throws IOException {
            out.writeLong(firstNum);
            out.writeLong(secondNum);
        }

        @Override
        public void readFields(DataInput in) throws IOException {
            firstNum = in.readLong();
            secondNum = in.readLong();
        }

        /*
         * 当key进行排序时会调用以下这个compreTo方法
         */
        @Override
        public int compareTo(MyNewKey anotherKey) {
            long min = firstNum - anotherKey.firstNum;
            if (min != 0) {
                // 说明第一列不相等,则返回两数之间小的数
                return (int) min;
            } else {
                return (int) (secondNum - anotherKey.secondNum);
            }
        }
    }

自定义分组

为了针对新的key类型作分组,我们也需要自定义一下分组规则:

(1)编写一个新的分组比较类型用于我们的分组:

 private static class MyGroupingComparator implements
            RawComparator<MyNewKey> {

        /*
         * 基本分组规则:按第一列firstNum进行分组
         */
        @Override
        public int compare(MyNewKey key1, MyNewKey key2) {
            return (int) (key1.firstNum - key2.firstNum);
        }

        /*
         * @param b1 表示第一个参与比较的字节数组
         *
         * @param s1 表示第一个参与比较的字节数组的起始位置
         *
         * @param l1 表示第一个参与比较的字节数组的偏移量
         *
         * @param b2 表示第二个参与比较的字节数组
         *
         * @param s2 表示第二个参与比较的字节数组的起始位置
         *
         * @param l2 表示第二个参与比较的字节数组的偏移量
         */
        @Override
        public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
            return WritableComparator.compareBytes(b1, s1, 8, b2, s2, 8);
        }

    }

从代码中我们可以知道,我们自定义了一个分组比较器MyGroupingComparator,该类实现了RawComparator接口,而RawComparator接口又实现了Comparator接口,下面看看这两个接口的定义:

  首先是RawComparator接口的定义:

public interface RawComparator<T> extends Comparator<T> {
  public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2);
}

其次是Comparator接口的定义:

public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
}

MyGroupingComparator中分别对这两个接口中的定义进行了实现,RawComparator中的compare()方法是基于字节的比较,Comparator中的compare()方法是基于对象的比较。

  在基于字节的比较方法中,有六个参数,一下子眼花了:

Params:

* @param arg0 表示第一个参与比较的字节数组
* @param arg1 表示第一个参与比较的字节数组的起始位置
* @param arg2 表示第一个参与比较的字节数组的偏移量

* @param arg3 表示第二个参与比较的字节数组
* @param arg4 表示第二个参与比较的字节数组的起始位置
* @param arg5 表示第二个参与比较的字节数组的偏移量

由于在MyNewKey中有两个long类型,每个long类型又占8个字节。这里因为比较的是第一列数字,所以读取的偏移量为8字节。

  (2)添加对分组规则的设置:

// 设置自定义分组规则
   job.setGroupingComparatorClass(MyGroupingComparator.class);
时间: 2024-10-08 10:04:22

MapReduce 学习4 ---- 自定义分区、自定义排序、自定义组分的相关文章

大数据入门第二十二天——spark(三)自定义分区、排序与查找

一.自定义分区 1.概述 默认的是Hash的分区策略,这点和Hadoop是类似的,具体的分区介绍,参见:https://blog.csdn.net/high2011/article/details/68491115 2.实现 package cn.itcast.spark.day3 import java.net.URL import org.apache.spark.{HashPartitioner, Partitioner, SparkConf, SparkContext} import s

Hadoop学习之路(6)MapReduce自定义分区实现

MapReduce自带的分区器是HashPartitioner原理:先对map输出的key求hash值,再模上reduce task个数,根据结果,决定此输出kv对,被匹配的reduce任务取走.自定义分分区需要继承Partitioner,复写getpariton()方法自定义分区类:注意:map的输出是<K,V>键值对其中int partitionIndex = dict.get(text.toString()),partitionIndex是获取K的值 附:被计算的的文本 Dear Dea

Hadoop学习之自定义二次排序

一.概述    MapReduce框架对处理结果的输出会根据key值进行默认的排序,这个默认排序可以满足一部分需求,但是也是十分有限的.在我们实际的需求当中,往 往有要对reduce输出结果进行二次排序的需求.对于二次排序的实现,本文将通过一个实际的MapReduce二次排序例子讲述 二次排序的实现和其MapReduce的整个处理流程,并且通过结果和map.reduce端的日志来验证所描述的处理流程的正确性. 二.需求描述 1.输入数据: sort1    1 sort2    3 sort2 

Spark 学习(四)RDD自定义分区和缓存

一,简介 二,自定义分区规则 2.1 普通的分组TopN实现 2.2 自定义分区规则TopN实现 三,RDD的缓存 3.1 RDD缓存简介 3.2 RDD缓存方式 正文 一,简介 在之前的文章中,我们知道RDD的有一个特征:就是一组分片(Partition),即数据集的基本组成单位.对于RDD来说,每个分片都会被一个计算任务处理,并决定并行计算的粒度.用户可以在创建RDD时指定RDD的分片个数,如果没有指定,那么就会采用默认值.默认值就是程序所分配到的CPU Core的数目.这个分配的规则我们是

hadoop MapReduce自定义分区Partition输出各运营商的手机号码

MapReduce和自定义Partition MobileDriver主类 package Partition; import org.apache.hadoop.io.NullWritable; import org.apache.hadoop.io.Text; public class MobileDriver { public static void main(String[] args) { String[] paths = {"F:\\mobile.txt", "F

Mapreduce中自定义分区

Reducer任务的数据来自于Mapper任务,也就说Mapper任务要划分数据,对于不同的数据分配给不同的Reducer任务运行.Mapper任务划分数据的过程就称作Partition.负责实现划分数据的类称作Partitioner. 默认的分区类是HashPartitioner,是处理Mapper任务输出的,getPartition()方法有三个形参,key.value分别指的是Mapper任务的输出,numReduceTasks指的是设置的Reducer任务数量,默认值是1.那么任何整数与

Hadoop自定义分区Partitioner

一:背景 为了使得MapReduce计算后的结果显示更加人性化,Hadoop提供了分区的功能,可以使得MapReduce计算结果输出到不同的分区中,方便查看.Hadoop提供的Partitioner组件可以让Map对Key进行分区,从而可以根据不同key来分发到不同的reduce中去处理,我们可以自定义key的分发规则,如数据文件包含不同的省份,而输出的要求是每个省份对应一个文件. 二:技术实现 自定义分区很简单,我们只需要继承抽象类Partitioner,实现自定义的getPartitione

在hadoop作业中自定义分区和归约

当遇到有特殊的业务需求时,需要对hadoop的作业进行分区处理 那么我们可以通过自定义的分区类来实现 还是通过单词计数的例子,JMapper和JReducer的代码不变,只是在JSubmit中改变了设置默认分区的代码,见代码: //1.3分区 //设置自定义分区类 job.setPartitionerClass(JPartitioner.class); //设置分区个数--这里设置成2,代表输出分为2个区,由两个reducer输出 job.setNumReduceTasks(2); 自定义的JP

hadoop编程小技巧(3)---自定义分区类Partitioner

Hadoop代码测试环境:Hadoop2.4 原理:在Hadoop的MapReduce过程中,Mapper读取处理完成数据后,会把数据发送到Partitioner,由Partitioner来决定每条记录应该送往哪个reducer节点,默认使用的是HashPartitioner,其核心代码如下: /** Use {@link Object#hashCode()} to partition. */ public int getPartition(K2 key, V2 value, int numRe

quick-cocos2d-x学习笔记【6】——制作自定义效果按钮菜单

前面提到的是基本的菜单使用,还是很容易的,不过我们在商业产品中,经常看到的按钮都是非常好看,不光光是图片做得精美,而且动画效果也很棒.Candy Crash都玩过吧,看它们那个按钮,真的像果冻一样,效果确实很赞,所以我们也来做个,当然不是它那个效果,而且点击之后有一个抖动的效果.像这样, 好了,开始做个吧,我这个也是搬了一下coinflip中的按钮代码,算是学习一下. 创建一个views文件夹,里面创建一个MyButton.lua文件,这个就是我们的自定义按钮类了.实现的原理比较简单,在ui.n