2016-04-08 12 views
1

だから私は電子メールのコレクションを持っているし、私がやりたいことはそうのような出力ユニークなトリプレット(送信者の電子メール、受信メール、タイムスタンプ)にそれらを使用している: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)に電子メールを送信します。 。受信者を格納するために、私はタイムスタンプと同様送信者受信者の電子メールアドレスを保持するデータ構造EdgeWritableWritableComparable)実装を作成し

私のマッパーは、次のようになります。

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ループを使用することは、私が考えることができる唯一のアプローチです。

これは「悪い」ですか?これがはっきりしていることを願っていますが、それ以上の明確化が必要な場合はお知らせください。

答えて

0

マップメソッドが各レコードに対して呼び出されるため、配列リストにはすべての呼び出しごとに1レコードしかありません。すべてのレコードの値を格納できるように、クラスレベルで配列リストを宣言します。その後、クリーンアップメソッドでは、マップの中に書いたemitロジックを実行することができます。これを試して、そのことがわかったら教えてください。

+0

私はそれがそのままで、プログラムが動作すると言わなければなりません。それは私がそれらをしたい正確に電子メールを出力します。私はちょうどforループを使用してこれが '不正な'か、悪い習慣と見なされているようなエッジを放出するかどうか疑問に思っています。私はMapReduceの例でそれを見たことがありません。どう思いますか? – wj1091

+0

ループでそれらを放出することに間違いはありません。マップメソッドから複数の値を出力できます。 – SurjanSRawat

関連する問題