Java Enhanced For Loop With Custom Types

By: Stephen Patrick | 30 Jun 2016 | Category: Java Constructs

Related Contents

Java Enhanced For Loop With Custom Types

The Java enhanced for loop simplifies the process of iterating arrays and collections. But what if you want to use this construct with custom java types. Let’s examine how we can perform this task. However, first we need to define some custom java types.

public class Car {
   private String make;
   private String model;
   private String color;

   public Car(String make, String model, String color) {
       this.make = make;
       this.model = model;
       this.color = color;
   }

   public String getColor() {
       return color;
   }

   public String getMake() {
       return make;
   }

   public String getModel() {
       return model;
   }

   public String toString() {
       return MessageFormat.format("Make: {0}, Model: {1}, Color: {2}", make,model,color);
   }
}


public class CarCollection {
   private List<Car> carList = new LinkedList<Car>();

   public void addCar(Car car) {
       carList.add(car);
   }

   public Iterator<Car> iterator() {
       return carList.iterator();
   }
}

Above we create two custom java types with very simple implementations. These types will be used to demonstrate the java enhanced for loop. Now let’s try to iterate a car collection instance.

public class CarCollectionConsoleRenderer {
   public void renderCars(CarCollection collection) {
       Iterator<Car> it = collection.iterator();
       for (Car c : it) {   // fails to compile
           System.out.println(c.toString());
       }
   }
}

Above we define a CarCollectionConsoleRenderer class. This class has the responsibility, to render a collection of cars to the console. A common idiom in java is to use an iterator to iterate a collection of elements.

Iterator<Car> it = collection.iterator();

The above code gets an iterator to iterate the collection of cars. However, when we attempt to compile this code it fails to compile. Our attempt to iterate the car collection using the enhanced for loop is not permitted.

for (Car c : it) {   // fails to compile
   System.out.println(c.toString());
}

In order to use our CarCollection Type with the java enhanced for loop we must implement the java.lang.Iterable interface.

public class CarCollection implements Iterable<Car>{
   private List<Car> carList = new LinkedList<Car>();

   public void addCar(Car car) {
       carList.add(car);
   }

   public Iterator<Car> iterator() {
       return carList.iterator();
   }
}

In the above code we modify our CarCollection class to implement the java.lang.Iterable interface. Now, lets modify our CarCollectionConsoleRenderer to render a given CarCollection using the java enhanced for loop.

public class CarCollectionConsoleRenderer {
   public void renderCars(CarCollection collection) {
       for (Car c :  collection) {
           System.out.println(c.toString());
       }
   }
}

Our CarCollectionConsoleRenderer is now more concise, we no longer need to explicitly declare an iterator and we can now iterate our car collection using the enhanced for loop. Finally, lets write some code, to invoke our CarCollectionConsoleRenderer class.

public static void main(String[] args) {
   CarCollection carCollection = new CarCollection();
   carCollection.addCar(new Car("Renault", "Stepway", "Grey"));
   carCollection.addCar(new Car("Ford", "Mustang", "Red"));

   CarCollectionConsoleRenderer renderer = new CarCollectionConsoleRenderer();
   renderer.renderCars(carCollection);
}

In the above code we define a main method. Within this method, we create a new CarCollection and add some cars. We then create an instance of the CarCollectionConsoleRenderer class. Finally, we invoke the renderCars method to render the collection of cars to the console.

The above code outputs the following when executed.

Make: Renault, Model: Stepway, Color: Grey
Make: Ford, Model: Mustang, Color: Red