欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解Java Streams 中的异常处理

程序员文章站 2024-02-25 10:11:34
前言: stream api 和 lambda 是java8的重要特性让我们可以使用更具功能性的语法风格。但是在编写的代码时候一个更大的问题是如何处理lambda中的已检...

前言:

stream api 和 lambda 是java8的重要特性让我们可以使用更具功能性的语法风格。但是在编写的代码时候一个更大的问题是如何处理lambda中的已检查异常。

但是不能直接调用从lambda抛出异常!但是可以在lambda中做一个简单的try-catch并将异常包装成一个runtimeexception。

/**###很显然这不是一种好的表现方式##**/ 
  /**
   * dosomething
   * @param item
   * @return
   */
  private static object dosomething(string item) {
    system.out.println("dosomething:\t" + item);
    return item;
  }
 
  public static void main(string[] args) {
    list<string> mylist = arrays.aslist("1", "2", "3", "4", "5", "6");
 
    mylist.stream().map(item -> {
      try {
        return dosomething(item);
      } catch (exception e) {
        throw new runtimeexception(e);
      }
    }).foreach(system.out::println);
  }

换一种可读性比较好的方式呢?

/**将函数体提取到一个单独的方法中,并调用新方法做try-catch处理**/  
 private object dosomething(string item) {
    system.out.println("dosomething:\t" + item);
    return item;
  }
 
  private object trysomething(string item) {
    try {
      return dosomething(item);
    } catch (exception e) {
      throw new runtimeexception(e);
    }
  }
 
  public void map() {
    list<string> mylist = arrays.aslist("1", "2", "3", "4", "5", "6");
    mylist.stream().map(this::dosomething).foreach(system.out::println);
  }

runtimeexception

在许多情况下对于一些运行时异常的捕捉都使用 runtimeexception 也可以在lambda内部调用。如果每个调用都进行运行时异常的捕获,重复代码就出现了。所以:将它抽象为实用函数,每次需要的时候调用它!

//定义一个检查接口
@functionalinterface
public interface checkedfunction<t,r> {
  r apply(t t) throws exception;
}

 您可以在此抽象接口中处理try-catch并将原始异常包装到 runtimeexception 中。

public static <t,r> function<t,r> wrap(checkedfunction<t,r> checkedfunction) {
 return t -> {
  try {
   return checkedfunction.apply(t);
  } catch (exception e) {
   throw new runtimeexception(e);
  }
 };
}

/**调用公共wrap 进行异常处理*/
public void map(){
    list<string> mylist = arrays.aslist("1", "2", "3", "4", "5", "6");
    mylist.stream()
      .map(wrap(item -> dosomething(item)))
      .foreach(system.out::println);
}

either

使用流时如果发生异常不希望停止处理流,either类型是函数式语言中的常见类型而不是java的一部分。与java中的optional类型类似,either是具有两种可能性的通用包装器。例如,如果我们有一个either值,那么这个值可以包含string类型或integer类型either<string,integer>。

public class either<l, r> {
  private final l left;
  private final r right;
  private either(l left, r right) {
    this.left = left;
    this.right = right;
  }
  public static <l,r> either<l,r> left( l value) {
    return new either(value, null);
  }
  public static <l,r> either<l,r> right( r value) {
    return new either(null, value);
  }
  public optional<l> getleft() {
    return optional.ofnullable(left);
  }
  public optional<r> getright() {
    return optional.ofnullable(right);
  }
  public boolean isleft() {
    return left != null;
  }
  public boolean isright() {
    return right != null;
  }
  public <t> optional<t> mapleft(function<? super l, t> mapper) {
    if (isleft()) {
      return optional.of(mapper.apply(left));
    }
    return optional.empty();
  }
  public <t> optional<t> mapright(function<? super r, t> mapper) {
    if (isright()) {
      return optional.of(mapper.apply(right));
    }
    return optional.empty();
  }
  public string tostring() {
    if (isleft()) {
      return "left(" + left +")";
    }
    return "right(" + right +")";
  }
}

让函数返回either 而不是抛出一个exception.

//只记录异常
public static <t,r> function<t, either> lift(checkedfunction<t,r> function) {
 return t -> {
  try {
   return either.right(function.apply(t));
  } catch (exception ex) {
   return either.left(ex);
  }
 };
}
 
//记录异常和值
public static <t,r> function<t, either> liftwithvalue(checkedfunction<t,r> function) {
 return t -> {
  try {
   return either.right(function.apply(t));
  } catch (exception ex) {
   return either.left(pair.of(ex,t));
  }
 };
}

/**调用either.lift 捕获异常继续执行*/
public void map(){
    list<string> mylist = arrays.aslist("1", "2", "3", "4", "5", "6");
    mylist.stream()
      .map(either.lift(item -> dosomething(item)))
      .foreach(system.out::println);
}

总结:

如果你想在lambda中调用它checkedexception,你可以将其包装成一个runtimeexception 。建议您创建一个抽象进行调用,这样您就不会每次try/catch。也可以使用  either 或其他类型来包装函数的结果,使流不会终止。

以上所述是小编给大家介绍的java streams 中的异常处理详解整合,希望对大家有所帮助