详解Java Streams 中的异常处理
作者:Go Big Or Go Home 发布时间:2021-09-03 11:26:11
前言:
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 中的异常处理详解整合网站的支持!
来源:https://blog.csdn.net/u011663149/article/details/88661591
猜你喜欢
- HTTP请求:如果需要Json格式的自己转下,度娘上N种姿势…//处理http请求 requestUrl为请求地址 requestMetho
- 原理比较简单,引入System.Reflection命名空间,利用反射查看某种Type下的方法,属性,字段和支持的接口等。using Sys
- 本文实例讲述了Android获取SD卡路径及SDCard内存的方法。分享给大家供大家参考。具体分析如下:昨天在研究拍照后突破的存储路径的问题
- 前言XML文件是一种常用的文件格式,例如WinForm里面的app.config以及Web程序中的web.config文件,还有许多重要的场
- 前言很多时候,我们定义接口或者调用别人的接口时,手里只有一份接口文档,文档中提供一段示例json格式的报文,我们需要根据json中的字段,挨
- 文件作为存储数据的单元,会根据数据类型产生很多分类,也就是所谓的文件类型。在对数据文件进行操作时,常常需要根据不同的文件类型来作不同的处理。
- 本文初步讲述了C#的CLR内存原理。这里所关注的内存里面说没有寄存器的,所以我们关注的只有托管堆(heap),栈(stack), 字符串常量
- 一、在spring的应用中我们存在两种过滤的用法,一种是 * 、另外一种当然是过滤器。我们这里介绍过滤器在springboot的用法,在sp
- 使用wait()和notify()实现Java多线程通信:两个线程交替打印A和B,如ABABABpublic class Test { &n
- 目录一 首先我们的去知道什么是反射?二(刨根问底)知道是什么还需要知道什么“成分”组成反射?2.1 Class 对象的获取及使用2.2 拿到
- 简单之美,springmvc,mybatis就是一个很好的简单集成方案,能够满足一般的项目需求。闲暇时间把项目配置文件共享出来,供大家参看:
- 如下所示:public class Test{public static void main(String[] args) {
- 有时候,我们需要把对象A的所有值复制给对象B(B = A),但是这样用等号给赋值你会发现,当B中的某个对象值改变时,同时也会修改到A中相应对
- 这是个我在C#调用批处理文件时遇到的问题。首先我通过Process.Start方法调用一个批处理文件,那个批处理文件里面则调用了一大堆程序。
- 用来练手还是不错的,分享大家看一下,还是一些新颖点的!哈哈 就是自定义DataGridView,方便每个功能部分调用!简单!再次重
- 这里以JDK 7U15在 Windows x86平台下的安装为例,其他平台安装与此类同。下载JDK请查看:JDK最新下载地址【含下载方法】①
- Java程序设计 图形用户界面 【九】单选按钮单选按钮 JRadioButtonJRadioButton类方法作用public JRadio
- 本文实例讲述了java GUI编程之paint绘制操作。分享给大家供大家参考,具体如下:import java.awt.*;public c
- PC端与Android手机端使用adb forword通信服务器端代码如下:import java.io.IOException; impo
- 本文实例为大家分享了Java执行SQL脚本文件到数据库的具体方式,供大家参考,具体内容如下方式一:直接读取SQL脚本文件的内容,然后传递到S