【问题标题】:Use of lamda expression in java 8在 java 8 中使用 lambda 表达式
【发布时间】:2019-07-15 14:06:55
【问题描述】:

我想重构这段代码以使用 lambda 表达式 java 8

for(int i = 0; i < customers.getCUSTOMER().size(); i++){
   if (customers.getCUSTOMER().get(i).getINCOME().getGROSSMONTH1().toBigInteger()
     < customers.getCUSTOMER().get(i).getINCOME().getNETTSALMONTH1().toBigInteger()){

        log.error("")
        throw new RuntimeException();
   }
}

【问题讨论】:

  • @Paul - 这是一个未经检查的异常,所以抛出它没有问题。
  • 顺便说一句,你不能用&lt;比较BigInteger
  • 好的,customers.getCUSTOMER().stream().filter(c -&gt; c.getINCOME().getGROSSMONTH1().toBigInteger().compareTo(c.getINCOME().getNETTSALMONTH1().toBigInteger()) == -1).findAny().ifPresent(c -&gt; { throw new RuntimeException(); }); 应该足够了。
  • @StephenC 我首先将它们转换为整数然后使用

标签: java lambda java-stream


【解决方案1】:

您正在迭代customers.getCUSTOMER() 的元素,这似乎是List(我假设它是一个)。那么,您大概会处理该列表的流:

customers.getCUSTOMER().stream()

您使用了每个元素的getINCOME() 两次,而根本没有使用它的任何其他方面,所以也许您想通过该方法映射元素。假设客户列表的元素类型为Customer,则可能是

        .map(Customer::getINCOME)

有多种方法可以从那里开始,但是由于您在满足条件时抛出异常,所以我个人会选择Stream.anyMatch()

        .anyMatch(x -> x.getGROSSMONTH1().toBigInteger().compareTo(
                x.getNETTSALMONTH1().toBigInteger()) < 0)

这会产生一个布尔结果,告诉您是否有任何元素满足条件,并且一旦找到满足条件的元素就会停止查找(anyMatch() 的谓词是 lambda)。您可以在类似于您现在拥有的 if 表达式中使用它:

if (customers.getCUSTOMER().stream()
        .map(Customer::getINCOME)
        .anyMatch(x -> x.getGROSSMONTH1().toBigInteger().compareTo(
                x.getNETTSALMONTH1().toBigInteger()) < 0) {
    log.error("")
    throw new RuntimeException();
}

由于您要抛出 RuntimeException,因此也可以在流中使用 lambda 来执行此操作,但如果您要抛出已检查的异常,则通常不可能。在检查异常的情况下,通常需要类似于此处介绍的内容。

另一方面,如果您想记录有关失败元素的信息,那么您需要在流中执行此操作。此外,在这种情况下,您可能希望跳过 map()。您可以改为基于谓词 filter() 和剩余元素中的 findFirst()(如果有的话,或者 findAny() 如果您不关心它是否是您报告的第一个)。结果是 Optional,如果存在,您可以使用另一个 lambda 进行处理:

customers.getCUSTOMER().stream()
        .filter(x -> x.getINCOME().getGROSSMONTH1().toBigInteger().compareTo(
                x.getINCOME().getNETTSALMONTH1().toBigInteger()) < 0)
        .findFirst()
        .ifPresent(x -> {
            log.error(x.getName() + " invalid: net salary is larger than gross")
            throw new RuntimeException();
        });

请注意,这并不能解决检查异常问题。您不能从 ifPresent lambda 内部抛出已检查异常。

【讨论】:

    【解决方案2】:
    customers.getCUSTOMER().stream().forEach(customer -> {
        if(customer.getINCOME().getGROSSMONTH1().toBigInteger() < customer.getINCOME().getNETTSALMONTH1().toBigInteger()){
          log.error("");
          throw new RuntimeException();
        }
    });
    

    您还应该尝试使用驼峰命名法重命名您的方法,例如 getIncome() 以使其更易于阅读并符合正常的 Java 编写标准。

    【讨论】:

      【解决方案3】:
      customers.getCUSTOMER().forEach(customer -> {
              if (customer.getINCOME().getGROSSMONTH1().toBigInteger() < 
                   customer.getINCOME().getNETTSALMONTH1().toBigInteger()) {
                  log.error("")
                  throw new RuntimeException();
              }
       });
      

      一个简单的方法

      另一种使用流和可选的方式:

        customers.stream().filter(customer ->    
                  customer.getINCOME().getGROSSMONTH1().toBigInteger() < 
                   customer.getINCOME().getNETTSALMONTH1().toBigInteger())
             .findAny().ifPresent(c -> {
                 log.error("")
                 throw new RuntimeException();
          });;
      

      【讨论】:

        【解决方案4】:

        通过使用 java-8 流,使用filter 作为条件,findFirst 在一场匹配后终止

        customers.getCUSTOMER().stream()
                               .filter(c->c.getINCOME().getGROSSMONTH1().toBigInteger() < c.getINCOME().getNETTSALMONTH1().toBigInteger())
                               .findFirst()
                               .ifPresent(cu->{
                                       log.error("")
                                       throw new RuntimeException();
                                   });
        

        【讨论】:

          【解决方案5】:

          在这种情况下,您需要的是BiPredicate&lt;TypeOfMonths&gt;,它看起来像这样

          BiPredicate<TypeOfMonths> biPredicate = (tom1, tom2) -> tom1.toBigInteger() < tom2.toBigInteger();
          

          那就这样用吧

          boolean shouldThrowException = customers.getCUSTOMER()
                                                  .stream()
                                                  .anyMatch(cust -> {
                                                      TypeOfMonth tom1 = getINCOME().getGROSSMONTH1();
                                                      TypeOfMonth tom2 = getINCOME()..getNETTSALMONTH1();
                                                      return biPredicate.test(tom1, tom2);
                                                  });
          
          if (shouldThrowException) {
              log.error("");
              throw new RuntimeException();
          }
          

          【讨论】:

            猜你喜欢
            • 2017-11-16
            • 1970-01-01
            • 2015-04-17
            • 1970-01-01
            • 1970-01-01
            • 2018-06-07
            • 1970-01-01
            • 2012-06-25
            • 2015-06-01
            相关资源
            最近更新 更多