Java mapreduce,对值进行排序

Java mapreduce,对值进行排序,java,sorting,hadoop,mapreduce,cloudera,Java,Sorting,Hadoop,Mapreduce,Cloudera,我有一个来自映射器的输出: Mapper: KEY, VALUE(Timestamp, someOtherAttrbibutes) 我的减速机确实收到: Reducer: KEY, Iterable<VALUE(Timestamp, someOtherAttrbibutes)> Reducer:键,可编辑 我希望Iterable按时间戳属性排序。有没有可能实施 我想避免在减速机代码中手动排序 我必须从Iterable“深度复制”所有对象,这可能会造成巨大的内存开销((这相对比较

我有一个来自映射器的输出:

Mapper: KEY, VALUE(Timestamp, someOtherAttrbibutes)
我的减速机确实收到:

Reducer: KEY, Iterable<VALUE(Timestamp, someOtherAttrbibutes)>
Reducer:键,可编辑
我希望
Iterable
时间戳属性排序。有没有可能实施

我想避免在减速机代码中手动排序


我必须从Iterable“深度复制”所有对象,这可能会造成巨大的内存开销((

这相对比较容易,您需要为
类编写comparator类


仔细看看这里:特别是在一个用于二次排序的解决方案部分。

这相对简单,您需要为
类编写comparator类


仔细看看这里:特别是在二次排序的解决方案部分。

您需要为您的值类编写comparator类

@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
    final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    List<String> list = new ArrayList<String>();
    for (Text val : values) {
        list.add(val.toString());

    }
    Collections.sort(list, new Comparator<String>() {
       public int compare(String s1, String s2) {
           String str1[] = s1.split(",");
           String str2[] = s2.split(",");
          int time1 = 0;
           int time2 = 0;
           try {
               time1 = (int)(sdf.parse(str1[0]).getTime());
               time2 = (int) (sdf.parse(str2[0]).getTime());

           } catch (ParseException e) {
               e.printStackTrace();
           } finally {
               return time1 - time2;
           }
       }
    });
    for(int i = 0; i < list.size(); ++i)
    context.write(key, new Text(list.get(i)));
}
@覆盖
受保护的void reduce(文本键、Iterable值、上下文上下文)引发IOException、InterruptedException{
最终简化格式sdf=新简化格式(“yyyy-MM-dd HH:MM:ss”);
sdf.setTimeZone(TimeZone.getTimeZone(“UTC”));
列表=新的ArrayList();
用于(文本值:值){
list.add(val.toString());
}
Collections.sort(list,newcomparator(){
公共整数比较(字符串s1、字符串s2){
字符串str1[]=s1.split(“,”);
字符串str2[]=s2.split(“,”);
int time1=0;
int time2=0;
试一试{
time1=(int)(sdf.parse(str1[0]).getTime();
time2=(int)(sdf.parse(str2[0]).getTime();
}捕获(解析异常){
e、 printStackTrace();
}最后{
返回时间1-时间2;
}
}
});
对于(int i=0;i
您需要为您的值类编写comparator类

@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
    final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    List<String> list = new ArrayList<String>();
    for (Text val : values) {
        list.add(val.toString());

    }
    Collections.sort(list, new Comparator<String>() {
       public int compare(String s1, String s2) {
           String str1[] = s1.split(",");
           String str2[] = s2.split(",");
          int time1 = 0;
           int time2 = 0;
           try {
               time1 = (int)(sdf.parse(str1[0]).getTime());
               time2 = (int) (sdf.parse(str2[0]).getTime());

           } catch (ParseException e) {
               e.printStackTrace();
           } finally {
               return time1 - time2;
           }
       }
    });
    for(int i = 0; i < list.size(); ++i)
    context.write(key, new Text(list.get(i)));
}
@覆盖
受保护的void reduce(文本键、Iterable值、上下文上下文)引发IOException、InterruptedException{
最终简化格式sdf=新简化格式(“yyyy-MM-dd HH:MM:ss”);
sdf.setTimeZone(TimeZone.getTimeZone(“UTC”));
列表=新的ArrayList();
用于(文本值:值){
list.add(val.toString());
}
Collections.sort(list,newcomparator(){
公共整数比较(字符串s1、字符串s2){
字符串str1[]=s1.split(“,”);
字符串str2[]=s2.split(“,”);
int time1=0;
int time2=0;
试一试{
time1=(int)(sdf.parse(str1[0]).getTime();
time2=(int)(sdf.parse(str2[0]).getTime();
}捕获(解析异常){
e、 printStackTrace();
}最后{
返回时间1-时间2;
}
}
});
对于(int i=0;i
我已经阅读了这篇文章,Hadoop《防御指南3》中也描述了同样的内容。据我所知,我必须将时间戳属性移动到key,并将key合成:[现有的\u key\u值,时间戳\u attr\u from\u值]。如果是这样,那么我不喜欢这种方法。至于我,这对我的业务任务来说是不自然的,可能会让其他开发人员感到困惑…:(我已经读过了。这不是我需要的东西:(问题是我需要为一个唯一键获取所有值,这些值应该按时间戳排序。如果我将时间戳移动到键,我将使用唯一键获取所有值。)(旧密钥时间戳)。这是不正确的。@Sergey我注意到你选择了这个答案作为正确的答案。它对你有用吗?二次嗨,是的,二次排序是解决这个问题的正确方法。@Matthew Moisen,是的。二次排序在列出的文章中有清楚的解释+我建议阅读Tom White Hadoop第三版。但最好的方法是使用apachepig。所有这些复杂的低级东西很久以前就已经在那里实现了。我读过这篇文章,防御指南3 Hadoop中也描述了类似的内容。据我所知,我必须将我的Timestamp属性移动到key,并使key复合:[现有的\u key\u值,Timestamp\u attr\u from\u值]。如果是这样,那么我不喜欢这种方法。至于我,这对我的业务任务来说是不自然的,可能会让其他开发人员感到困惑…:(我已经读过了。这不是我需要的东西:(问题是我需要为一个唯一键获取所有值,这些值应该按时间戳排序。如果我将时间戳移动到键,我将使用唯一键获取所有值。)(旧密钥时间戳)。这是不正确的。@Sergey我注意到你选择了这个答案作为正确的答案。它对你有用吗?二次嗨,是的,二次排序是解决这个问题的正确方法。@Matthew Moisen,是的。二次排序在列出的文章中有清楚的解释+我建议阅读Tom White Hadoop第三版。但最好的方法是使用apache猪。所有这些复杂的低级东西很久以前就在那里实现了。