CSMR for large-scale text-prcessing
public class CSMRReducer extends Reducer&lt;IntWritable, DocumentWritable ,Text, 
        VectorArrayWritable&gt; {

    private ArrayList&lt;DocumentWritable&gt; al;
    private VectorWritable[] val;
    private VectorArrayWritable vaw; 

    @Override
    public void reduce(IntWritable key, Iterable&lt;DocumentWritable&gt; values, 
            Context context) throws IOException, InterruptedException{
        al = new ArrayList();
        vaw = new VectorArrayWritable();

        /* Storing each key-value pair (document) in a java.util.ArrayList */
        for (DocumentWritable v : values){
            al.add(new DocumentWritable(v.getKey(),v.getValue()));
        }

        /* Generating all the possible combinations of documents */
        if (al.size()&gt;0){
            for (int i=0;i&lt;al.size();++i){
                for (int j=i+1;j&lt;al.size();++j){
                    val = new VectorWritable[2];

                    /* Generating the key for the current document pair with
                        the format "doci_name@docj_name" */
                    String k = al.get(i).getKey().toString()+
                            "@"+al.get(j).getKey().toString();

                    //First Document (doci)
                    val[0] = new VectorWritable(al.get(i).getValue().get());
                    //Second Document (docj)
                    val[1] = new VectorWritable(al.get(j).getValue().get());
                    vaw.set(val);

                    context.write(new Text(k), vaw);
                }
            }  
        }
    }

}


You can remove the fields and just declare the variables in the function. There's no need for class variables here.

You can also remove the al.size()&gt;0 check, because that's automatically checked by the for loop.

On the performance end, you could prepare al.get(i) and al.get(i).getKey().toString()+"@" before going into the j loop.