查找相同字母组成的字谜

import java.io.IOException;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;


import java.util.Arrays;
import java.util.StringTokenizer;


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
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.Tool;
import org.apache.hadoop.util.ToolRunner;


public class AnagramMain extends Configured implements Tool{
//这个mapper类是一个泛型类型,有四个形参类型,分别制定map函数的输入键/输入值/输出键/输出值,任何map函数都套用这个公式

//当一个字段需要使用多个类型的时候,用Object类型,Text相当于java中的String类型
//使用static修饰是为了方便调用,开发工具最好用static修饰,如果不修饰,则这些方法属于该类的对象,我们的先创建对象在调用方法,那么将会创建很多对象,则会占很多内存
public static class AnagramMapper extends Mapper<Object, Text, Text, Text>{
//定义两个变量,输入key得变量和输出值的变量
private Text sortedText = new Text();
private Text orginalText = new Text();

public void map(Object key,Text value,Context context)throws IOException,InterruptedException{
String word = value.toString();//将单词转化为string类型
char[] wordChars =word.toCharArray();//单词转化为字符数组
Arrays.sort(wordChars);//数组进行排序

String sortedWord =new String(wordChars);//字符数组转化为字符串,new一个字符串对象

sortedText.set(sortedWord);//设置输出key的值

orginalText.set(word);//设置输出value的值

context.write(sortedText, orginalText);//输出结果


}
}


//设置reduce函数
public static class AnagramReducer extends Reducer<Text, Text, Text, Text>{

//定义两个输出变量
private Text outputKey = new Text();
private Text outputValue = new Text();


public void reduce(Text Key,Iterable<Text>Value,Context context)throws IOException,InterruptedException{
//设置一个输出变量并初始化
String output = "";
//对相同字母组成的单词,使用~符号进行拼接
for(Text anagram:Value){
if(!output.equals("")){
output = output + "~";//如果当前结果不等于"",则输出"~"
}
output = output + anagram.toString();//最后把输出结果变成字符串
}
StringTokenizer outputTokenizer = new StringTokenizer(output, "~");
if(outputTokenizer.countTokens() >=2){//因为单词最少有两个,所以这里设置为2

output = output.replace("~", ",");
outputKey.set(Key.toString());//设置key的值
outputValue.set(output);//设置value的值
context.write(outputKey, outputValue);//输出reducer的结果

}

}
}
public static void main(String[] args) throws Exception {

//数据输入路径和输出路径

String[] args0 = {"hdfs://justinyang:9000/anagram/anagram.txt/",
"hdfs://justinyang:9000/anagram/output/"};

int ec = ToolRunner.run(new Configuration(),new AnagramMain(),args0);
System.exit(ec);
}


@SuppressWarnings("deprecation")
@Override
public int run(String[] args)throws Exception{
Configuration conf = new Configuration();
Path mypath = new Path(args[1]);
FileSystem hdfs = mypath.getFileSystem(conf);//获取文件系统.get方法用户获取某个字段存储的值
if(hdfs.isDirectory(mypath)){
hdfs.delete(mypath,true);
}
//构建job对象,指定了作业执行范围,可以用它来控制整个作业的运行
Job job = new Job(conf,"testAnagram");
/*
* 我们在集群运行作业的时候,要把代码打包成一个jar文件,然后把jar文件上传到集群上,通过命令来执行整个作业,但是命令不必指定jar文件的名称,所以通过job对象的set
* 方法中传递一个主类,hadoop会通过这个主类来查找包含它的jar文件
*/
job.setJarByClass(AnagramMain.class);//set一个jar包 通过一个类来调用括号里面就是我们要调用的那个类 ,因为我们求字谜 所以是AnagramMain

//指定mapper和reducer的类,set方法用于给某一字段设置需要存储的值
job.setMapperClass(AnagramMapper.class);
job.setMapOutputKeyClass(Text.class);//指定mapper输出key类型
job.setMapOutputValueClass(Text.class);//指定mapper输出value类型
//还有一个setCombinerClass也可以,combiner相当于是小的reducer程序,不会对reducer有影响,但在最后输出结果前可以先进行筛选处理.
job.setReducerClass(AnagramReducer.class);
job.setOutputKeyClass(Text.class);//指定reduce输出key类型
job.setOutputValueClass(Text.class);//指定reduce输出value类型

//指定数据的输入和输出路径
FileInputFormat.addInputPath(job, new Path(args[0]));//这个路径可以是单个的文件、一个目录(此时,将目录下所有文件当作输入)或符合特定文件模式的一系列文件
FileOutputFormat.setOutputPath(job, new Path(args[1]));//只能有一个输出路径,该路径指定的就是reduce函数输出文件的写入目录




//提交作业
job.waitForCompletion(true);

return 0;
}


}

单元测试

import java.io.IOException;
import java.util.List;
import java.sql.Driver;
import org.apache.hadoop.io.IntWritable;
//import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
//import org.apache.hadoop.mapred.Reducer;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mrunit.mapreduce.MapDriver;
import org.junit.Before;
import org.junit.Test;










/**
 * Mapper 端的单元测试
 */
@SuppressWarnings("all")
public class AnagramMainMapperTest {
private Mapper mapper;//定义一个Mapper对象
private MapDriver driver;//定义一个MapDriver 对象


@Before
public void init() {
mapper = new AnagramMain.AnagramMapper();//实例化一个AnagramMain中的AnagramMapper对象
driver = new MapDriver(mapper);//实例化MapDriver对象
}

@Test
public void test() throws IOException {
//输入一行测试数据,
String Word ="ecdab";
driver.withInput(new Object(), new Text(Word))//跟AnagramMapper输入类型一致
.withOutput(new Text("abcde"), new Text("ecdab"))//跟AnagramMapper输出类型一致,看是否能排序结果没问题
.runTest();
}

}

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.sql.Driver;


import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;


import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mrunit.mapreduce.ReduceDriver;
import org.junit.Before;
import org.junit.Test;
import org.mockito.asm.tree.analysis.Value;
/**
 * Reducer 单元测试
 */
@SuppressWarnings("all")
public class AnagramMainReduceTest {
private Reducer reducer;//定义一个Reducer对象
private ReduceDriver driver;//定义一个ReduceDriver对象


@Before
public void init() {
reducer = new AnagramMain.AnagramReducer();//实例化一个AnagramMain中的AnagramReducer对象
driver = new ReduceDriver(reducer);//实例化ReduceDriver对象
}



@Test
public void test() throws IOException {
//新建一个Key,key的值是不变的
Text key = new Text("abcde"); 
//在新建数组列表中写入2组字母的Value值,目的验证其最后是否按预定格式输出,因为我们需要是把相同字母组成的所有字谜输出,并用","分割
List values = new ArrayList();  
values.add(new Text("caebd"));
values.add(new Text("bcade"));


driver.withInput(key, values)
     .withOutput(key, new Text("caebd,bcade"))  //验证是否按此格式输出
     .runTest();

}

}


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.sql.Driver;


//import org.apache.hadoop.io.IntWritable;
//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.mrunit.TestDriver;
import org.apache.hadoop.mrunit.mapreduce.MapReduceDriver;
import org.junit.Before;
import org.junit.Test;


/**
 * Mapper 和 Reducer 集成起来测试
 */
@SuppressWarnings("all")
public class AnagramMainTest {
private Mapper mapper;//定义一个Mapper对象
private Reducer reducer;//定义一个Reducer对象
private MapReduceDriver driver;//定义一个MapReduceDriver 对象


@Before
public void init() {
mapper = new AnagramMain.AnagramMapper();//实例化一个AnagramMain中的AnagramMapper对象
reducer = new AnagramMain.AnagramReducer();//实例化一个AnagramMain中的AnagramReducer对象
driver = new MapReduceDriver(mapper, reducer);//实例化MapReduceDriver对象
}


@Test
public void test() throws IOException {
//新建一个Key,key的值是不变的
String Word = "ebacd";
String Word2 = "eabcd";



driver.withInput(new Object(), new Text(Word))
.withInput(new Object(), new Text(Word2))
     .withOutput(new Text("abcde"), new Text("ebacd,eabcd"))  //验证是否按此格式输出
     .runTest();

}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值