-3

我正在玩 Java Streams,我想知道是否有任何方法可以创建这样的代码块->

if(givenString.equals("productA")) {
    return new productA();
} else if(givenString.equals("productB") {
    return new productB();
} .....

像这样进入Java Stream ->

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()
4

2 回答 2

2

您不想在流中内联。相反,请编写一个辅助方法来执行此操作:

private static Product createByString(String name) {
    // I assume Product is a common superclass
    // TODO: implement
}

现在的问题是:这个方法应该如何实现?

  1. 使用大的 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字符串上的 a 被编译成一个跳转表,所以你不会有n字符串比较。
    缺点:你不能在运行时扩展它,你必须保持这个方法同步。

  2. 使用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();
    }
    

    优点:通过一些简单的修改,您可以在此实现中添加新产品,甚至替换它们。
    缺点:有一些适度的开销,你仍然需要维护"productA"它和它的类型之间的映射。

  3. 使用反射。
    每个问题看起来都像钉子的好旧锤子。

    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);
         }
    }
    

    优点:你不需要做绑定。
    缺点:很慢。

于 2019-08-30T15:56:19.973 回答
0

在下面的第一个示例中:


    if(givenString.equals("productA")) {
        return new productA();
    } else if(givenString.equals("productB") {
        return new productB();
    } 

您正在返回通过字符串指定的某个对象的实例。在我看来,如果您知道字符串,您可以立即创建对象,而无需使用中间方法调用来执行此操作。

另一种可能性是类名是通过一些用户输入提供的。在这种情况下,您可能需要考虑reflection完成此操作,以便可以引用新创建的类的方法和字段。

无论哪种情况,我都怀疑streams这种要求是一种合理的方法。

于 2019-08-30T14:23:29.183 回答