【问题标题】:How do i abstract the common parts of Java for loop so as to avoid repetition/duplication我如何抽象Java for循环的公共部分以避免重复/重复
【发布时间】:2018-03-29 06:27:16
【问题描述】:

我有一个接收事物列表的方法,迭代列表并在每次迭代时执行 XYZ 操作。 “XYZ 事物”的定义取决于实现或我想要实现的目标。 对于某些人来说,我只想运行一些 SQL 来访问数据库并更新客户姓名和发票到期日。对于其他人,我只想更新税额、逾期天数等。情况总是不同的。我如何只创建一个可重用的方法,而不是重复这个方法,这不是“OnceAndOnlyOnce”的精神。

  DaoProvider daoProvider;

  public void buildAndUpdateCustomer(List<Object> list) {
    for (Object obj : list) {
      Map<String, Object> m = (Map<String, Object>) obj;
      Map<String, Object> args = new HashMap<>();
      for (Map.Entry<String, Object> x : m.entrySet()) {
        args.put(x.getKey(), x.getValue());
      }
      //these are my XYZ things...
      daoProvider.updateCustomerName();
      daoProvider.updateAgingMia();
    }
}


  public void buildAndUpdateTax(List<Object> list) {
    for (Object obj : list) {
      Map<String, Object> m = (Map<String, Object>) obj;
      Map<String, Object> args = new HashMap<>();
      for (Map.Entry<String, Object> x : m.entrySet()) {
        args.put(x.getKey(), x.getValue());
      }
      daoProvider.updateTaxAmount();
    }
}

  public void buildAndUpdateLedgerBal(List<Object> list) {
    for (Object obj : list) {
      Map<String, Object> m = (Map<String, Object>) obj;
      Map<String, Object> args = new HashMap<>();
      for (Map.Entry<String, Object> x : m.entrySet()) {
        args.put(x.getKey(), x.getValue());
      }
      daoProvider.updateLedgerBalance();
    }
}

【问题讨论】:

  • 你能以任何方式区分这些列表吗?
  • public void buildAndProcess(List&lt;Object&gt; list, Consumer&lt;Object&gt; processor) {。附言看看你的代码,你可能有太多 Object - Java 是一种强类型语言,当有人有这么多 Object 和这么多的转换时,这是一个尖叫的危险信号。一般来说,一个人根本不应该看到太多Object 的用法......
  • 另外,代码没有意义——大概你应该将args 传递给调用。这又给我带来了另一个问题——你似乎使用List&lt;Object&gt;Map&lt;String, Object&gt; 作为本质上的通用参数——这是一个非常讨厌的反模式,它删除了编译器提供的所有类型安全,甚至删除了名称检查。我会强烈建议阅读一本关于 OO 编程的书。
  • @boristhespider 这不是生产代码。将要投入生产的版本已经有了泛型。
  • @JoshUzo 仿制药不是灵丹妙药。如果您仍然传递 Map 作为一种存储方式,本质上是 kwargs,那么该方法从根本上被破坏了。

标签: java for-loop arraylist foreach iteration


【解决方案1】:

您可以将通用代码移动到私有辅助方法中:

@SuppressWarnings("unchecked")
private static Map<String, Object> getArgs(Object obj) {
    Map<String, Object> m = (Map<String, Object>) obj;
    Map<String, Object> args = new HashMap<>();
    for (Map.Entry<String, Object> x : m.entrySet()) {
        args.put(x.getKey(), x.getValue());
    }
    return args;
}

public void buildAndUpdateCustomer(List<Object> list) {
    for (Object obj : list) {
        Map<String, Object> args = getArgs(obj);
        // these are my XYZ things...
        daoProvider.updateCustomerName(args);
        daoProvider.updateAgingMia(args);
    }
}

public void buildAndUpdateTax(List<Object> list) {
    for (Object obj : list) {
        Map<String, Object> args = getArgs(obj);
        daoProvider.updateTaxAmount(args);
    }
}

public void buildAndUpdateLedgerBal(List<Object> list) {
    for (Object obj : list) {
        Map<String, Object> args = getArgs(obj);
        daoProvider.updateLedgerBalance(args);
    }
}

或者使用 Java 8,您可以使用 lambdas:

@SuppressWarnings("unchecked")
private static void buildAndUpdate(List<Object> list, Consumer<Map<String, Object>> consumer) {
    for (Object obj : list) {
        Map<String, Object> m = (Map<String, Object>) obj;
        Map<String, Object> args = new HashMap<>();
        for (Map.Entry<String, Object> x : m.entrySet()) {
            args.put(x.getKey(), x.getValue());
        }
        consumer.accept(args);
    }
}

public void buildAndUpdateCustomer(List<Object> list) {
    buildAndUpdate(list, args -> {
        daoProvider.updateCustomerName(args);
        daoProvider.updateAgingMia(args);
    });
}

public void buildAndUpdateTax(List<Object> list) {
    buildAndUpdate(list, args -> daoProvider.updateTaxAmount(args));
}

public void buildAndUpdateLedgerBal(List<Object> list) {
    buildAndUpdate(list, args -> daoProvider.updateLedgerBalance(args));
}

【讨论】:

    【解决方案2】:

    我将假设 args 因此需要传递到方法中:

    public void buildAndUpdateCustomer(List<Object> list) {
        for (Object obj : list) {
          Map<String, Object> m = (Map<String, Object>) obj;
          Map<String, Object> args = new HashMap<>();
          for (Map.Entry<String, Object> x : m.entrySet()) {
            args.put(x.getKey(), x.getValue());
          }
          //these are my XYZ things...
          daoProvider.updateCustomerName(args);
          daoProvider.updateAgingMia(args);
        }
    }
    

    然后我们可以写一个方法:

    public void buildAndProcess(List<Object> list, Consumer<Object> processor) {
        for (Object obj : list) {
          Map<String, Object> m = (Map<String, Object>) obj;
          Map<String, Object> args = new HashMap<>();
          for (Map.Entry<String, Object> x : m.entrySet()) {
            args.put(x.getKey(), x.getValue());
          }
          processor.accept(args);
        }
    }
    

    而你之前的方法变成:

    public void buildAndUpdateCustomer(List<Object> list) {
        buildAndProcess(list, args -> {
          //these are my XYZ things...
          daoProvider.updateCustomerName(args);
          daoProvider.updateAgingMia(args);
        });
    }
    

    这段代码很奇怪:

    Map<String, Object> m = (Map<String, Object>) obj;
    Map<String, Object> args = new HashMap<>();
    for (Map.Entry<String, Object> x : m.entrySet()) {
        args.put(x.getKey(), x.getValue());
    }
    

    等同于Map&lt;String, Object&gt; args = new HashMap&lt;&gt;((Map&lt;String, Object&gt;) obj);


    我将重申我在 cmets 中所说的话:

    看看你的代码,你可能有太多 Object - Java 是一种强类型语言,当有人有这么多 Object 并且这么多转换时,这是一个尖叫的危险信号。一般来说,Object 的用法应该不会太多

    您似乎使用 List&lt;Object&gt;Map&lt;String, Object&gt; 作为本质上的通用参数 - 这是一个非常讨厌的反模式,它删除了编译器提供的所有类型安全,甚至删除了名称检查。

    【讨论】:

      猜你喜欢
      • 2018-08-25
      • 1970-01-01
      • 2021-09-21
      • 2014-10-21
      • 1970-01-01
      • 1970-01-01
      • 2019-06-24
      • 2013-04-30
      • 2020-03-10
      相关资源
      最近更新 更多