今日は冬至ですね。
かぼちゃとゆず湯が私を待っている・・・。
リファクタリングに入ります。
要リファクタリング箇所
- 警告が色々出ている
- mapperが固定値のハードコーディングでcontext.write()を読んでいる。
Eclipseの「問題」ビューを見てみましょう。
Mapper.Context は raw 型です。総称型 Mapperという警告がLogAnalysisMapper.javaとTestLogAnalysisMapper.javaに出ています。また、.Context への参照は、パラメーター化する必要があります。
型の安全性: メソッド write(Object, Object) は raw 型 TaskInputOutputContext に属しています。総称型 TaskInputOutputContextという警告がLogAnalysisMapper.javaとTestLogAnalysisMapper.javaに出ています。への参照はパラメーター化される必要があります
これらの原因は実は同じで、Mapper<KEYIN, KEYOUT, VALUEIN, VALUEOUT>に具体的な型を指定する必要があると言うことを言っています。
今回のMapの入力のキーはLongWritableです(これはほぼお約束)。入力の値はファイルの各行なので、Text型になります。出力のキーは、抽出した行になるので、Text型です。出力の値は、実は特に何でもいいのですが、今回はLongWritableとしましょう。
つまり、
Mapper<LongWritable, Text, Text, LongWritable>.Contextと書けばいいことになります。
実際に書いてみましょう。
Test側は、contextの初期化の所に警告が残りました。
ソースファイルはコンパイルエラーとなってしまいました。
コンパイルエラーはよくないので、早速消します。
Mapper.write()がコンパイルエラーになっています。
どうやら、mapメソッドの引数の型とMapper<LongWritable, Text, Text, LongWritable>で指定した型が一致してないようです。Object型を指定しているところをLongWritable, Textで書き換えます。
コンパイルが通りました。一方、Test側のコードですが、こちらは消えそうにないですね。
こちらは放置しましょう。
では、コンパイルが通ったので実行します。
ロジックを一切触っていないので、JUnitはGREENになるはずです。
GREENになることを確認したら、次のリファクタリングに進みます。
今回、map関数内でwriteしている文字列はもともとVALUEとして引き渡されてくるものですね。
では、引数のvalueをそのままwriteしてしまいましょう。
context.write(value, new LongWritable(1));では、JUnitを実行してみます。
ちゃんとGREENになりました。リファクタリング成功です!!
ということで今回はこの辺で。
今回までのソースです。
TestLogAnalysisMapper.java
/*
* TestLogAnalysisMapper.java
*/
package jp.co.littel.hadoop;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.internal.verification.Times;
/**
* ログ分析Mapperプログラム テストプログラム
* @author yoshitsugu
*/
public class TestLogAnalysisMapper {
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* 抽出するパターン
* @throws Exception 例外発生時
*/
@Test
public void testMapExtract() throws Exception {
Mapper<LongWritable, Text, Text, LongWritable>.Context context = mock(Mapper.Context.class);
String[] lines = {
"2009-12-14 00:00:26,340 INFO hogehoge @ abcdefg hijklmn opqrstu"
};
LogAnalysisMapper mapper = new LogAnalysisMapper();
mapper.map(null, new Text(lines[0]), context);
verify(context, new Times(1)).write(new Text(lines[0]), new LongWritable(1));
}
}
LogAnalysisMapper.java
/*
* LogAnalysisMapper.java
*/
package jp.co.littel.hadoop;
import java.io.IOException;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
/**
* ログ解析Mapperプログラム
* @author m.yoshitsugu
*/
public class LogAnalysisMapper extends Mapper{
/* (non-Javadoc)
* @see org.apache.hadoop.mapreduce.Mapper#map(java.lang.Object, java.lang.Object, org.apache.hadoop.mapreduce.Mapper.Context)
*/
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
context.write(value, new LongWritable(1));
}
}
0 件のコメント:
コメントを投稿