使用 Java 流基于字符串创建新对象
Create new Objects based on a String with Java Stream
我正在玩 Java Streams,我想知道是否有任何方法可以创建这样的代码块 ->
if(givenString.equals("productA")) {
return new productA();
} else if(givenString.equals("productB") {
return new productB();
} .....
像这样进入 Java 流 ->
Stream.of(givenString)
.filter(e -> e.equal("productA)")
.map(e -> new productA())
我遇到了这个可行的解决方案,但我不相信...
Stream.of(givenString)
.map(e -> e -> e.equals("productA)" ? new productA() : new productB())
.findAny()
.get()
在下面的第一个示例中:
if(givenString.equals("productA")) {
return new productA();
} else if(givenString.equals("productB") {
return new productB();
}
您正在返回通过字符串指定的某个对象的实例。在我看来,如果您知道字符串,就可以立即创建对象,而无需使用中间方法调用。
另一种可能性是 class 名称是通过某些用户输入提供的。在这种情况下,您可能需要考虑 reflection
来完成此操作,以便您可以引用新创建的 class.
的方法和字段
无论哪种情况,我都怀疑 streams
是满足此类要求的合理方法。
您不想在流中内联执行该操作。取而代之的是,编写一个辅助方法来做到这一点:
private static Product createByString(String name) {
// I assume Product is a common superclass
// TODO: implement
}
现在的问题是:这个方法应该如何实现?
使用大 switch 语句。
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");
}
}
专业版:字符串上的 switch
被编译成跳转表,因此您不会进行 n
字符串比较。
缺点:你不能在运行时扩展它,你必须保持这个方法同步。
使用一个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:通过一些简单的修改,您可以将新产品添加到此实现中,甚至替换它们。
缺点:有一些适度的开销,你仍然需要维护 "productA"
和它的类型之间的映射。
使用反射。
每个问题看起来都像钉子的好旧锤子。
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);
}
}
亲:您不需要进行绑定。
缺点:速度慢。
我正在玩 Java Streams,我想知道是否有任何方法可以创建这样的代码块 ->
if(givenString.equals("productA")) {
return new productA();
} else if(givenString.equals("productB") {
return new productB();
} .....
像这样进入 Java 流 ->
Stream.of(givenString)
.filter(e -> e.equal("productA)")
.map(e -> new productA())
我遇到了这个可行的解决方案,但我不相信...
Stream.of(givenString)
.map(e -> e -> e.equals("productA)" ? new productA() : new productB())
.findAny()
.get()
在下面的第一个示例中:
if(givenString.equals("productA")) {
return new productA();
} else if(givenString.equals("productB") {
return new productB();
}
您正在返回通过字符串指定的某个对象的实例。在我看来,如果您知道字符串,就可以立即创建对象,而无需使用中间方法调用。
另一种可能性是 class 名称是通过某些用户输入提供的。在这种情况下,您可能需要考虑 reflection
来完成此操作,以便您可以引用新创建的 class.
无论哪种情况,我都怀疑 streams
是满足此类要求的合理方法。
您不想在流中内联执行该操作。取而代之的是,编写一个辅助方法来做到这一点:
private static Product createByString(String name) {
// I assume Product is a common superclass
// TODO: implement
}
现在的问题是:这个方法应该如何实现?
使用大 switch 语句。
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"); } }
专业版:字符串上的
switch
被编译成跳转表,因此您不会进行n
字符串比较。
缺点:你不能在运行时扩展它,你必须保持这个方法同步。使用一个
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:通过一些简单的修改,您可以将新产品添加到此实现中,甚至替换它们。
缺点:有一些适度的开销,你仍然需要维护"productA"
和它的类型之间的映射。使用反射。
每个问题看起来都像钉子的好旧锤子。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); } }
亲:您不需要进行绑定。
缺点:速度慢。