Java 8 introduced some impressive new features. Lambdas in conjunction with Streams finally support a functional style of programming.
But, unlike LINQ of the .NET world, there is no operator to join streams. Thus, I tried to join streams manually. My approach is to use second a stream in a lambda expression within a map operation. Other options are thinkable.Here a very simple example, without further explanation:
package com.mycompany.testlambda;
import java.util.ArrayList;
import java.util.List;
public class Starter {
public static void main(String[] args) {
List<Color> colors = initColors();
// just print the color names
colors.stream().forEach(color -> System.out.println(color.getName()));
List<Car> cars = new ArrayList<>();
initCars(cars);
// just print the car names
cars.stream().map(car -> car.getName()).forEach(System.out::println);
// next, join color name to car and print carName: colorName
// sample 1: access to collection
cars.stream()
.map(car -> car.getName() + ": " + colors
.get(car.getColorId())
.getName())
.forEach(System.out::println);
// sample 2: "joining" streams
cars.stream()
.map(car -> car.getName() + ": " + colors
.stream()
.filter(color -> color.getId() == car.getColorId())
.findAny().get().getName())
.forEach(System.out::println);
}
private static void initCars(List<Car> cars) {
cars.add(new Car("VW", 1));
cars.add(new Car("Ford", 2));
cars.add(new Car("Chevrolet", 1));
cars.add(new Car("BMW", 3));
cars.add(new Car("Ferrari", 1));
cars.add(new Car("Mercedes", 2));
cars.add(new Car("Mercedes", 3));
}
private static List<Color> initColors() {
List<Color> colors = new ArrayList<>();
colors.add(new Color(0, "unknown"));
colors.add(new Color(1, "red"));
colors.add(new Color(2, "green"));
colors.add(new Color(3, "blue"));
return colors;
}
}
When nesting streams, as in “Sample 2”, the call to the outer reference car.getColorId() is inefficient, because the result will be the same for each element of the inner stream. The inner lambda closes over the current “car” element of the outer lambda. Instead, I suggest caching the result of car.getColorId() in a local variable of the outer lambda and comparing color.getColorId() to that variable. In this simple example. the inefficiency is negligible. In real world applications, the redundancy cost could be very expensive.
Jeffrey,
With respect to performance, you’re absolutely right. My example isn’t optimized for anything. I just wanted to create a simple “join” of streams without considering any other aspect.
Michael