详解Java Streams 中的异常处理

 更新时间:2019年03月22日 14:11:44   作者:Go Big Or Go Home  
这篇文章主要介绍了Java Streams 中的异常处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言:

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 中的异常处理详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • 详细谈谈Java中long和double的原子性

    详细谈谈Java中long和double的原子性

    原子性是指一个操作或多个操作要么全部执行,且执行的过程不会被任何因素打断,要么就都不执行,下面这篇文章主要给大家介绍了关于Java中long和double原子性的相关资料,需要的朋友可以参考下
    2021-08-08
  • springboot动态调用实现类方式

    springboot动态调用实现类方式

    这篇文章主要介绍了springboot动态调用实现类方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • 简述Java中的四种引用类型

    简述Java中的四种引用类型

    从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用,下面分别介绍下这四种引用。
    2021-04-04
  • SpringBoot一个非常蛋疼的无法启动的问题解决

    SpringBoot一个非常蛋疼的无法启动的问题解决

    这篇文章主要介绍了SpringBoot一个非常蛋疼的无法启动的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • SpringBoot依赖注入的三种方式

    SpringBoot依赖注入的三种方式

    本文将通过代码示例详细介绍SpringBoot依赖注入的三种方式,对学习依赖注入有一定的参考价值,需要的朋友可以参考一下
    2023-04-04
  • SpringBoot项目如何设置权限拦截器和过滤器

    SpringBoot项目如何设置权限拦截器和过滤器

    这篇文章主要介绍了使用lombok时如何自定义get、set方法问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • SpringBoot增强Controller方法@ControllerAdvice注解的使用详解

    SpringBoot增强Controller方法@ControllerAdvice注解的使用详解

    这篇文章主要介绍了SpringBoot增强Controller方法@ControllerAdvice注解的使用详解,@ControllerAdvice,是Spring3.2提供的新注解,它是一个Controller增强器,可对controller进行增强处理,需要的朋友可以参考下
    2023-10-10
  • 关于ApplicationContext的三个常用实现类

    关于ApplicationContext的三个常用实现类

    这篇文章主要介绍了关于ApplicationContext的三个常用实现类,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • SpringMVC 传日期参数到后台的实例讲解

    SpringMVC 传日期参数到后台的实例讲解

    下面小编就为大家分享一篇SpringMVC 传日期参数到后台的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • Java程序的逻辑控制和方法详解

    Java程序的逻辑控制和方法详解

    这篇文章主要介绍了Java程序的逻辑控制和方法详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04

最新评论