Iterate without an index
Use for each liberally
Remove from a collection
import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.ListIterator; import java.util.Set; import java.util.Vector; import java.util.stream.IntStream; public class IterationExamples { public static void main(String... args) { IterationExamples examples = new IterationExamples(); examples.forLoopWithIntegerIndex(); examples.enhancedFor(); examples.explicitIterator(); examples.listIterator(); examples.overAnEnumeration(); examples.simpleDoWhileLoop(); examples.streamsAndLambdas(); } /** Common error: off-by-one in the index value. */ void forLoopWithIntegerIndex(){ logTitle("Normal for loop."); for(int idx=0; idx < NAMES.size(); ++idx){ log(NAMES.get(idx)); } } /** More compact, less error-prone than the for-loop with an int index. */ void enhancedFor(){ logTitle("Enhanced-for loop. JDK 1.5+"); for(String name : NAMES){ log(name); } } /** A common reason for using an Iterator is to remove items from the collection. With a normal enhanced-for loop, you can't modify the underlying collection while you're iterating over it. */ void explicitIterator(){ logTitle("Explicit Iterator. JDK 1.5+"); //not used here, since the Set is unmodifiable: //Set<String> letters = Set.of("alpha", "beta", " ", "gamma"); //LinkedHashSet is modifiable (and has a predictable iteration order) Set<String> letters = new LinkedHashSet<>(); letters.add("alpha"); letters.add("beta"); letters.add(""); // an empty string letters.add("gamma"); log("Before: " + letters); //now remove any empty strings from the collection Iterator<String> iter = letters.iterator(); while(iter.hasNext()){ if (iter.next().trim().length() == 0){ //this only works if the collection supports 'remove' iter.remove(); } } log("After: " + letters); /* This second style has the advantage that the iterator object is confined to the for-loop; however, it's not as legible as the previous style. */ logTitle("Explicit iterator with a for-loop."); for (Iterator<String> iter2 = letters.iterator(); iter2.hasNext();){ log(iter2.next()); } } /** ListIterator is for Lists only. */ void listIterator(){ logTitle("ListIterator can add-remove-change. JDK1.5+"); List<Integer> years = new ArrayList<>(); years.add(1775); years.add(1925); years.add(1929); log("Before: " + years); ListIterator<Integer> iter = years.listIterator(); while (iter.hasNext()){ Integer value = iter.next(); if (value >= 1900){ iter.set(value - 1); } else if (value < 1800){ iter.remove(); } } log("After: " + years); } /** Enumerations are used by older APIs. When defining new code, you should almost always use Collections and Maps instead. */ void overAnEnumeration(){ //Vector is an older class, usually avoided in new code Vector<String> v = new Vector<>(); v.add("alpha"); v.add("beta"); v.add("gamma"); Enumeration<String> e = v.elements(); logTitle("Enumeration, with a while loop."); while (e.hasMoreElements()){ log(e.nextElement()); } } /** do-while isn't used often. It differs from the while-loop in the placement of the boolean test. In a do-while loop, the loop body is executed at least once. */ void simpleDoWhileLoop(){ logTitle("Do-while."); int countDown = 5; do { log(countDown); --countDown; } while(countDown > -1); } /** @since Java 8 */ void streamsAndLambdas(){ logTitle("Iterable.forEach(Consumer). JDK 8+"); //Iterable now has a functional-friendly forEach method that //takes a Consumer, so you don't even need an intermediate stream NAMES.forEach(name -> log(name)); logTitle("Explicit stream with a lambda expression. JDK 8+"); NAMES.stream().forEach(name -> log(name)); logTitle("Explicit stream with a method reference expression. JDK 8+"); NAMES.stream().forEach(System.out::println); logTitle("Using a stream in a second style, for N-line methods. JDK 8+"); NAMES.stream().forEach(name -> { log(name.toLowerCase()); log(name.toUpperCase()); }); logTitle("IntStream has a compact way of defining ranges of integers."); IntStream.range(10,20).forEach(i -> log(i)); } /** Warning: List.of() returns an unmodifiable list. */ private List<String> NAMES = List.of("Ann", "Bob", "Charles", "Diane"); private static final void log(Object thing){ System.out.println(" " + thing.toString()); } private static final void logTitle(Object thing){ System.out.println(thing.toString()); } }