とにかく、各レデューサープロセスが処理する必要がある要素またはレコードの数を決定できる方法はありますか?
2 に答える
短い答え - いいえ、リデューサーは、イテラブルによっていくつの値がサポートされているかを事前に知りません。これを行う唯一の方法は、反復しながらカウントすることですが、反復可能オブジェクトを再度反復することはできません。
長い答え - iterable の裏付けは、実際にはシリアル化されたキーと値のペアのソートされたバイト配列です。レデューサーには 2 つのコンパレーターがあります。1 つはキーと値のペアをキー順に並べ替え、もう 1 つはキー間の境界を決定します (キー グルーパーと呼ばれます)。通常、キーグルーパーはキー順序付けコンパレーターと同じです。
特定のキーの値を反復処理する場合、基になるコンテキストは配列内の次のキーを調べ、グループ化コンパレータを使用して前のキーと比較します。コンパレータがそれらが等しいと判断した場合、反復が続行されます。それ以外の場合、この特定のキーの反復は終了します。したがって、特定のキーに対して渡される値の数を事前に決定することはできないことがわかります。
Text/IntWritable ペアなどの複合キーを作成すると、実際にこれを確認できます。compareTo メソッドでは、最初に Text で並べ替え、次に IntWritable フィールドで並べ替えます。次に、キーのテキスト部分のみを考慮するグループ コンパレータとして使用する Comparator を作成します。レデューサーで値を反復すると、反復ごとに変化するキーの IntWritable 部分を観察できるはずです。
このシナリオを示すために以前に使用したいくつかのコードは、このペーストビンにあります
レデューサー クラスは MapReducer Reduce クラスを拡張する必要があります。
Reducer<KEYIN,VALUEIN,KEYOUT,VALUEOUT>
次に、拡張された Reduce クラスで指定された KEYIN/VALUEIN 引数を使用して reduce メソッドを実装する必要があります。
reduce(KEYIN key, Iterable<VALUEIN> values,
org.apache.hadoop.mapreduce.Reducer.Context context)
特定のキーに関連付けられた値は、
int count = 0;
Iterator<VALUEIN> it = values.iterator();
while(it.hasNext()){
it.Next();
count++;
}
ただし、値セットを2回通過しないように、他の処理と一緒にこのカウントを行うことをお勧めします。
編集
これは、追加するにつれて動的に拡大するベクトルの例です (したがって、配列を静的に宣言する必要がないため、値セットのサイズは必要ありません)。これは、非通常のデータ (つまり、入力 csv ファイルのすべての行で列数が同じではない) に最適ですが、オーバーヘッドが最も大きくなります。
Vector table = new Vector();
Iterator<Text> it = values.iterator();
while(it.hasNext()){
Text t = it.Next();
String[] cols = t.toString().split(",");
int i = 0;
Vector row = new Vector(); //new vector will be our row
while(StringUtils.isNotEmpty(cols[i])){
row.addElement(cols[i++]); //here were adding a new column for every value in the csv row
}
table.addElement(row);
}
次に、N 番目の行の M 番目の列にアクセスできます。
table.get(N).get(M);
ここで、列数が設定されることがわかっている場合は、これを変更して配列のベクトルを使用することができます。これは、おそらく少し高速でスペース効率が高いでしょう。