i m playing around with Java Streams and I wonder if there is any way to create a code Block like this ->
if(givenString.equals("productA")) {
return new productA();
} else if(givenString.equals("productB") {
return new productB();
} .....
into a Java Stream like this ->
Stream.of(givenString)
.filter(e -> e.equal("productA)")
.map(e -> new productA())
i came across with this solution which works but i m not convinced...
Stream.of(givenString)
.map(e -> e -> e.equals("productA)" ? new productA() : new productB())
.findAny()
.get()
You don't want to do that inline in a stream. Instead, write a helper method that does just that:
private static Product createByString(String name) {
// I assume Product is a common superclass
// TODO: implement
}
Now the question is: How should this method be implemented?
Use a big switch statement.
private static Product createByString(String name) {
switch (name) {
case "productA": new productA();
case "productB": new productB();
// ... maybe more?
default: throw new IllegalArgumentException("name " + name + " is not a valid Product");
}
}
Pro: a switch
on a string is compiled into a jumptable, so you won't have n
string comparisons.
Con: You can't extend it at runtime, and you have to keep this method in sync.
Use a HashMap<String,Supplier<Product>>
.
private static final Map<String,Supplier<Product>> productConstructors = new HashMap<>();
static {
productConstructors.put("productA", productA::new);
productConstructors.put("productB", productB::new);
}
private static Product createByString(String name) {
Supplier<Product> constructor = productConstructors.get(name);
if (constructor == null) {
// Handle this?
throw new IllegalArgumentException("name " + name + " is not a valid Product");
}
return constructor.get();
}
Pro: with some easy modifications you can add new products to this implementation, or even replace them.
Con: has some moderate overhead, and you still need to maintain a the mapping between "productA"
and it's type.
Use reflection.
The good old hammer where every problem looks like a nail.
private static Product createByString(String name) {
try {
return Class.forName("your.pkgname. " + name).asSubclass(Product.class).getConstructor().newInstance();
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
Pro: You don't need to do the binding.
Con: It's slow.