使用Java Stream基于字符串创建新对象

时间:2019-08-30 11:20:17

标签: java string java-stream predicate supplier

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

{
    "errorMessage": "client.put(...).promise is not a function",
    "errorType": "TypeError",
    "stackTrace": [
        "module.exports.myHero (/var/task/create.js:30:27)"
    ]
}

进入这样的Java流->

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

我遇到了这个可行的解决方案,但是我不相信...

Stream.of(givenString)
      .filter(e -> e.equal("productA)")
      .map(e -> new productA())   

2 个答案:

答案 0 :(得分: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被编译为跳转表,因此您不会进行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);
         }
    }
    

    专业人士:您不需要进行绑定。
    缺点:很慢。

答案 1 :(得分:0)

在下面的第一个示例中:


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

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

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

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