Reputation: 6126
I have a class that constructs several foo objects. The problem right now is that the class iterates one by one down a list and builds them. I want to see if there's a way to make all of the building happen in parallel. Here's the class in question:
public List<Foo> create() {}
List<Class> fooTypes = Arrays.asList(
Foo1.class,
Foo2.class,
Foo3.class,
Foo4.class,
Foo5.class,
Foo6.class
);
List<Foo> foos = new ArrayList<>();
for(Class<? extends Foo> fooType : fooTypes) {
Optional<Foo> foo = findByType(fooType);
if(foo.isPresent()) {
foos.add(foo.get());
}
}
return foos;
}
private Optional<Foo> findByType(Class<? extends Foo> fooClass) {
if(fooClass.isAssignableFrom(Foo1.class)) {
return Optional.ofNullable(foo1());
}
if(fooClass.isAssignableFrom(Foo2.class)) {
return Optional.ofNullable(foo2());
}
if(fooClass.isAssignableFrom(Foo3.class)) {
return Optional.ofNullable(foo3());
}
if(fooClass.isAssignableFrom(Foo4.class)) {
return Optional.ofNullable(foo4());
}
if(fooClass.isAssignableFrom(Foo5.class)) {
return Optional.ofNullable(foo5());
}
if(fooClass.isAssignableFrom(Foo6.class)) {
return Optional.ofNullable(foo6());
}
return Optional.empty();
}
private Alert foo1() {
return new Foo1Builder().build();
}
private Alert foo2() {
return new Foo2Builder().build();
}
private Alert foo3() {
return new Foo3Builder().build();
}
private Alert foo4() {
return new Foo4Builder().build();
}
private Alert foo5() {
return new Foo5Builder().build();
}
private Alert foo6() {
return new Foo6Builder().build();
}
Is there a way to convert the foreach
loop into a java 8 parallel stream? If not, is going the executor route outlined here the correct way to go? I tried something like this to implement parallel streams but something is just not correct:
foos = fooTypes
.parallelStream()
.filter(a -> findByType(a).isPresent())
.map(Optional::get)
.collect(Collectors.toList());
Upvotes: 1
Views: 1628
Reputation: 692191
A parallel stream will be much less efficient than a sequential stream for such a small number of elements. It's overkill.
But you can use a Stream, indeed:
foos = fooTypes
.stream()
.map(this::findByType)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
That said, I really don't know what you gain by iterating on the classes to find which method to call on each class. Why not just use
return Arrays.asList(new Foo1Builder().build(),
new Foo2Builder().build(),
...);
It seems much less convoluted to me.
Upvotes: 4