【问题标题】:Java 8 refactor switch statement that does different things for each caseJava 8 重构 switch 语句,为每种情况做不同的事情
【发布时间】:2018-01-29 14:23:55
【问题描述】:

我有一个 switch 语句,它遍历 json 文件并根据文件中的属性执行不同的操作。例如:

dataMap.forEach((k, v) -> {
        Product product = new Product();
        ProductLine productLine = new ProductLine();
        Vendor currentVendor = new Vendor();

        // Step over each atttribute in the line of the file
        v.forEach((k2, v2) -> {
            switch(k2) {
                case "Product Class": {
                    Set<ProductCategory> categories = new HashSet<>();
                    try {
                        List<String> categoryList = Arrays.asList(v2.split(","));
                        categoryList.forEach(it ->{
                            ProductCategory category = ProductCategory.loadTypeByValue(it.trim());
                            categories.add(category);
                        });                     
                        product.setProductCategories(categories);
                    } catch (Exception e) {
                        //
                    }
                    break;
                }                
                case "Product Name": {
                    product.setName(v2);
                    productLine.setName(v2);
                    break;
                }
                case "SKU": {
                    product.setSKU(v2);
                    break;
                }
                case "Name": {
                    vendor.setName(v2);
                }
           ....

由于这些 case 语句适用于不同的对象(ProductProductLineVendor),并且每个 case 有时都需要 ProducerConsumerFunction 接口,我该如何重构整个开关(最好使用某种形式的 Lambda)?我想用一个 Map,key 是这样的,比如“Product Class”,但是值是什么?

Map <String, ?> = new HashMap<>();

感谢您的帮助!

【问题讨论】:

  • 不能创建一个反映json结构的类,只解析输入吗?

标签: java java-8 switch-statement refactoring


【解决方案1】:

嗯,我想我已经回答了我自己的问题。我将每个案例定义为BiConsumer&lt;String, Object&gt;(),并为每个属性及其 BiConsumer 设置一个Map,如下所示:

final static Map<String, BiConsumer<String, Object>> attributeMap = new HashMap<>();

private BiConsumer<String, Object> setVendorName = new BiConsumer<String, Object>() { 
    @Override
    public void accept(String value, Object obj) {
        ((Vendor)obj).setName(value);
    }
};

attributeMap.put("Vendor Name", setVendorName);

【讨论】:

  • 您不必使用 BiConsumer。您可以编写自己的接口,使用接受值、产品和供应商的方法。
  • 谢谢。不过,我并不总是需要所有三个参数。所以我只是在 for-each 中添加了一个 if 语句。
  • 不要使用对象。想想其他人使用你的代码。
【解决方案2】:

这只是想法,但为什么不做这样的事情:

dataMap.forEach((k, v) -> {
        Product product = new Product();
        ProductLine productLine = new ProductLine();
        Vendor currentVendor = new Vendor();

    List<Entry<K,V>> vSet = v.entrySet();
    vSet.stream().filter((v)->"Product Class".equals(v.getKey()))
             .foreach((v)->addCategoriesToProduct(product, v.getKey(), v.getValue()));


    vSet.stream().filter(((v)->"Product Name".equals(v.getKey()))
             .foreach((v)->fillProductName(product, v.getValue()));


    vSet.stream().filter((v)->"SKU".equals(v.getKey()))
             .foreach((v)->fillProductName(product, v.getValue()));

编辑:也许他想要这样的想法;

r = new ProductAttributeResolver( v.entrySet());

product.setCategories(r.getAllCategories());
product.setName(r.getProductName());
...

那么 getProductName 将如下所示:

   return vSet.stream().filter(((v)->"Product Name".equals(v.getKey()))
             .map((v)->v.getValue())
             .findFirst()
             .orElse(null)

【讨论】:

  • 这看起来很酷,但我的领导不喜欢 forEach 语句。他告诉我使用创建者/解析者模式,我不知道那是什么!
  • 喜欢与否对代码的工作方式没有影响,告诉他掌握现实。 ;)
  • 你不只是三倍迭代次数吗?
  • @GhostCat = 过滤器是关键。 :D
  • 我看到您正在过滤。但这仍然意味着您的总迭代次数是 三倍。您仍然必须检查流中的每个元素并对其应用过滤器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-30
  • 2020-04-16
  • 1970-01-01
相关资源
最近更新 更多