Java – what is the best way to navigate complex trees of different objects?
For example:
class Vehicle {
Collection<Axle> axles;
}
class Axle {
Collection<Wheel> wheels;
}
class Wheel {
// I think there are dually rims that take two tires -- just go with it
Collection<Tire> tires;
}
class Tire {
int width;
int diameter;
}
I have a service through which I can get a collection of all vehicle objects I know Now that I have a tire of a specific width and diameter, I want to find a vehicle that can accept it The simple approach is to have a set of four nested loops, as follows:
for (Vehicle vehicle : vehicles) {
for (Axle axle : vehicle.getAxles()) {
for (Wheel wheel : axle.getWheels()) {
for (Tire tire : wheel.getTires()) {
if (tire.width == targetWidth
&& tire.diameter == targetDiameter) {
// do something
break;
}
}
}
}
}
Is there a good design pattern? Or do you want to use a better data structure? Would it be better to keep an index in the location mapped to the tire information of the vehicle?
Editor: answer questions in comments
yes
yes
Not special
Sometimes it's just a vehicle, sometimes it's just an axle – two different environments
Yes, when I need the shaft
Edit2: further expand metaphor to explain the above two situations:
Background 1 – I want to know the vehicle, so I can send a worker to collect the vehicle and bring it back
Background 2 – I want to know the axles and tires because I'm trying to do this for the vehicle
Solution
You can use Java 8 streams to flatten loops
vehicles.stream()
.flatMap(vehicle -> vehicle.getAxles().stream())
.flatMap(axle -> axle.getWheels().stream())
.flatMap(wheel -> wheel.getTires().stream())
.filter(tire -> tire.width == targetWidth
&& tire.diameter == targetDiameter)
.forEach(tire -> {
// do something
});
The advantage of streaming is that you can insert additional filters, filters, findany, etc. anywhere in the sequence
