Reputation: 1008
I was wondering if I can join two pre-sorted streams (in a single pass). For example, if I have the following Java classes:
public class Person { // constructor & getters ommitted
private String name;
private int salary;
private List<Car> cars;
public void addCar(Car c) { cars.add(c); }
}
public class Car { // constructor & getters ommitted
private String owner;
private String brand;
}
And I have pre-sorted streams, as in:
Stream<Person> clients = Arrays.asList(
new Person("Anne", 500),
new Person("Johnny", 340)
).stream();
Stream<Car> cars = Arrays.asList(
new Car("Johnny", "Mazda"),
new Car("Johnny", "Fiat"),
new Car("Mary", "Volvo")
).stream();
I wanted to apply addCar()
to Johnny with the "Mazda" and "Fiat". There's no car for Anne, and Mary is not a client.
Is it possible to join both streams with a single pass on the streams?
I've seen solutions where one stream is walked multiple times, but since they are pre-ordered, I guess there could be a chance of doing it in one pass.
EDIT: The expected result of the operation would be to call addCar()
twice for "Johnny": once with the "Mazda", once with the "Fiat".
Upvotes: 3
Views: 632
Reputation: 31878
A precompute can help. Something like
Map<String, List<Car>> cars = Stream.of(
new Car("Johnny", "Mazda"),
new Car("Johnny", "Fiat"),
new Car("Mary", "Volvo"))
.collect(Collectors.groupingBy(Car::getOwner));
Stream.of(new Person("Anne", 500),
new Person("Johnny", 340))
.forEachOrdered(p -> cars.getOrDefault(p.getName(),
Collections.emptyList()).forEach(p::addCar));
Upvotes: 1
Reputation: 2492
I am afraid it's not possible to efficiently solve this task using Stream API. But you can still do it using iterators.
public static void addCars(Stream<Person> clients, Stream<Car> cars) {
Iterator<Person> clientsIt = clients.iterator();
Iterator<Car> carsIt = cars.iterator();
Person client = null;
while (carsIt.hasNext()) {
Car car = carsIt.next();
while (client == null || !client.getName().equals(car.getOwner())) {
if(!clientsIt.hasNext()) return;
client = clientsIt.next();
}
client.addCar(car);
}
}
Upvotes: 3