だから私は電子メールのコレクションを持っているし、私がやりたいことはそうのような出力ユニークなトリプレット(送信者の電子メール、受信メール、タイムスタンプ)にそれらを使用している:forループを介してMapReduceの中間キーを出す - 私はMapReduceを誤解していますか?基本例が含まれています。
[email protected] [email protected] 09/12/2009 16:45
[email protected] [email protected] 09/12/2009 18:45
[email protected] [email protected] 07/05/2008 12:29
上記の例では、ユーザ1は、単一を送りました複数の受信者(ユーザー2とユーザー9)に電子メールを送信します。 。受信者を格納するために、私はタイムスタンプと同様送信者と受信者の電子メールアドレスを保持するデータ構造EdgeWritable
(WritableComparable)
実装を作成し
私のマッパーは、次のようになります。
private final EdgeWritable edge = new EdgeWritable(); // Data structure for triplets.
private final NullWritable noval = NullWritable.get();
...
@Override
public void map(Text key, BytesWritable value, Context context)
throws IOException, InterruptedException {
byte[] bytes = value.getBytes();
Scanner scanner = new Scanner(new ByteArrayInputStream(bytes), "UTF-8");
String from = null; // Sender's Email address
ArrayList<String> recipients = new ArrayList<String>(); // List of recipients' Email addresses
long millis = -1; // Date
// Parse information from file
while(scanner.hasNext()) {
String line = scanner.nextLine();
if (line.startsWith("From:")) {
from = procFrom(stripCommand(line, "From:")); // Get sender e-mail address.
} else if (line.startsWith("To:")) {
procRecipients(stripCommand(line, "To:"), recipients); // Populate recipients into a list.
} else if (line.startsWith("Date:")) {
millis = procDate(stripCommand(line, "Date:")); // Get timestamp.
if (line.equals("")) { // Empty line indicates the end of the header
break;
}
}
scanner.close();
// Emit EdgeWritable as intermediate key containing Sender, Recipient and Timestamp.
if (from != null && recipients.size() > 0 && millis != -1) {
//EdgeWritable has 2 Text values (ew[0] and ew[1]) and a Timestamp. ew[0] is the sender, ew[1] is a recipient.
edge.set(0, from); // Set ew[0]
for(int i = 0; i < recipients.size(); i++) {
edge.set(1, recipients.get(i)); // Set edge from sender to each recipient i.
edge.setTS(millis); // Set date.
context.write(edge, noval); // Emit the edge as an intermediate key with a null value.
}
}
}
...
私のレデューサーは日付をフォーマットし、エッジを出力するだけです。
public void reduce(EdgeWritable key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {
String date = MailReader.sdf.format(edge.getTS());
out.set(edge.get(0) + " " + edge.get(1) + " " + date); // same edge from Mapper (an EdgeWritable).
context.write(noval, out); // same noval from Mapper (a NullWritable).
}
EdgeWritableを中間キーとして使用し、値(マッパー内)としてNullWritableを使用する必要があるため、他の方法を使用することはできません。これは私の最初のHadoop/MapReduceプログラムであり、私は正しい方向に進んでいることを知りたがっています。私はMapReduceの例をたくさんオンラインで見てきましたが、キーと値のペアがfor-loopで私がやったように放出されることはありませんでした。私はここでいくつかの種類のトリックが欠けているように感じますが、このようにforループを使用することは、私が考えることができる唯一のアプローチです。
これは「悪い」ですか?これがはっきりしていることを願っていますが、それ以上の明確化が必要な場合はお知らせください。
私はそれがそのままで、プログラムが動作すると言わなければなりません。それは私がそれらをしたい正確に電子メールを出力します。私はちょうどforループを使用してこれが '不正な'か、悪い習慣と見なされているようなエッジを放出するかどうか疑問に思っています。私はMapReduceの例でそれを見たことがありません。どう思いますか? – wj1091
ループでそれらを放出することに間違いはありません。マップメソッドから複数の値を出力できます。 – SurjanSRawat