Gli stream forniscono un'astrazione molto migliore per la composizione delle diverse operazioni che vuoi eseguire in aggiunta alle raccolte o agli stream di dati in arrivo. Specialmente quando devi mappare gli elementi, filtrarli e convertirli. 
 Il tuo esempio non è molto pratico. Considera  il seguente codice dal sito Oracle . 
List<Transaction> groceryTransactions = new Arraylist<>();
for(Transaction t: transactions){
  if(t.getType() == Transaction.GROCERY){
    groceryTransactions.add(t);
  }
}
Collections.sort(groceryTransactions, new Comparator(){
  public int compare(Transaction t1, Transaction t2){
    return t2.getValue().compareTo(t1.getValue());
  }
});
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t: groceryTransactions){
  transactionsIds.add(t.getId());
}
 può essere scritto usando i flussi: 
List<Integer> transactionsIds = 
    transactions.stream()
                .filter(t -> t.getType() == Transaction.GROCERY)
                .sorted(comparing(Transaction::getValue).reversed())
                .map(Transaction::getId)
                .collect(toList());
 La seconda opzione è molto più leggibile. Quindi, quando hai cicli nidificati o loop diversi che eseguono l'elaborazione parziale, è un'ottima candidata per l'utilizzo delle API Streams / Lambda.