代码之家  ›  专栏  ›  技术社区  ›  Andrew Cheong

如何在要返回的方法中从lambda返回值?

  •  0
  • Andrew Cheong  · 技术社区  · 7 年前

    如何在要返回的方法中从lambda返回值?

    最初,我有:

    myCollection.forEach(item -> {
      try {
        doSomething(item);
      } catch (Exception e) {
        return "There was a problem doing something: " + e.getMessage();
      }
    });
    

    但我的目的是回到方法上 包含 所有这些代码,不只是返回lambda。因此,我不得不这样做:

    String error = "";
    myCollection.stream().filter(item -> {
      try {
        doSomething(item);
        return true;
      } catch (Exception e) {
        error = "There was a problem doing something: " + e.getMessage();
      }
      return false;
    });
    if (!error.isEmpty()) {
      return error;
    }
    

    但这不是最好的办法。Java 8的功能和优雅的实现方式是什么?

    4 回复  |  直到 7 年前
        1
  •  1
  •   Valentin Ruano    7 年前

    你真的需要在这里使用Lambda吗?最好的Java方法是对集合中的每一个使用1.5:

    try {
      for (final E item : myCollection) {
         doSomething(item)
      }
    } catch (final Exception ex) {
      return "blah";
    }
    

    请注意,在进入和退出 try-catch 因此,最好将其置于循环之外。

        2
  •  1
  •   grape_mao    7 年前

    也许是这样的,我还没有测试过。

       myCollection.stream().map(item -> {
          try {
            doSomething(item);
            return null;
          } catch (Exception e) {
            return "There was a problem doing something: " + e.getMessage();
          }
        }).filter(exp -> exp!=null).findFirst();
    
        3
  •  1
  •   Sweeper    7 年前

    从溪流内部抛出的任何东西都可以用 try 围绕流的子句。

    try {
        myCollection.forEach(SurroundingClass::doSomething);
    } catch (Exception e) {
        return "..."
    }
    

    但是,我不建议使用异常作为流控制的一种方式。抛出和捕获异常的速度很慢。在将数据传递给之前,应始终检查数据是否会产生异常 doSomething 如果可以的话。

    如果您谈论的是已检查的异常,那么没有简单的方法来处理它们。看看这个 post 如果你想知道一些(相当长的)变通方法。

        4
  •  0
  •   Nikolai Shevchenko    7 年前

    lambdas中已检查异常的处理可以通过以下方式实现

        @FunctionalInterface
        public interface ThrowingConsumer<T, E extends Exception> {
            void accept(T t) throws E;
        }
    
        private static <T> Consumer<T> wrap(ThrowingConsumer<T, Exception> throwingConsumer) {
            return item -> {
                try {
                    throwingConsumer.accept(item);
                } catch (Exception ex) {
                    throw new RuntimeException(ex);
                }
            };
        }
    
        private String processCollection(List</* whatever type */> myCollection) {
            try {
                myCollection.forEach(wrap(this::doSomething));
            } catch (Exception e) {
                return e.getMessage(); // error
            }
            return null; // no error
        }