Sei sicuro che il codice che hai postato sia quello che stai usando? Perchè quello non potrà mai produrre il risultato che hai postato tu:

codice:
for(Esame e : lista){
   if(e.getVoto() != 0)
      n = max - e.nome.length();
      s = e.getNome() + punti(n);
      if(e.getCFU() < 10)
         s = s + "  " + e.getCFU() + " CFU - " + e.getVoto() + "/30";
      else
         s = s + " " + e.getCFU() + " CFU - " + e.getVoto() + "/30";
}
return s;
L'istruzione in grassetto, ad ogni iterazione della lista, butta via tutto quello che avevi salvato nella variabile "s" fino a quel momento... quindi, al massimo, stamperà solo i voti dell'ultimo esame.

PS:
codice:
if(max == 0 || max < len)
Non ha senso verificare che max sia uguale a 0... è sufficiente il test sulla lunghezza. Nessuna stringa potrà mai avere una lunghezza inferiore allo 0 e anche se fosse... non sarebbe maggiore di "max".

PPS: consiglio di usare uno StringBuilder ed il relativo metodo append() piuttosto che la concatenazione di stringhe: è più efficiente.

Ciao.