网易首页 > 网易号 > 正文 申请入驻

java培训:java流中的异常处理方法分享

0
分享至

以下文章来源于IT码徒

自版本 8 以来,Stream API 和 lambda 是 Java 的一大改进。从那时起,我们可以使用更具功能性的语法风格。现在,在使用这些代码结构几年之后,仍然存在的更大问题之一是如何处理 lambda 中的已检查异常。

大家可能都知道,不可能直接调用从 lambda 引发检查异常的方法。在某种程度上,我们需要捕获异常以使代码编译。当然,我们可以在 lambda 中做一个简单的 try-catch 并将异常包装到 a RuntimeException中,如第一个示例所示,但我认为我们都同意这不是最好的方法。

myList.stream()
.map(item -> {
try {
return doSomething(item);
} catch (MyException e) {
throw new RuntimeException(e);
}
})
.forEach(System.out::println);

我们大多数人都知道块 lambda 很笨重且可读性较差。在我看来,它们应该尽可能地避免。如果我们需要做的不仅仅是一行,我们可以将函数体提取到一个单独的方法中,然后简单地调用新方法。解决此问题的更好且更易读的方法是将调用包装在一个普通的旧方法中,该方法执行 try-catch 并从您的 lambda 中调用该方法。

myList.stream()
.map(this::trySomething)
.forEach(System.out::println);
private Item trySomething(Item item) {
try {
return doSomething(item);
} catch (MyException e) {
throw new RuntimeException(e);
}
}

这个解决方案至少更具可读性,我们确实将我们的关注点分开。如果您真的想捕获异常并做一些特定的事情,而不是简单地将异常包装到 a RuntimeException中,那么这对您来说可能是一个可行且可读的解决方案。

1运行时异常

在许多情况下,您会看到人们使用这些类型的解决方案将异常重新打包到 RuntimeException未经检查的异常的一个或更具体的实现中。通过这样做,可以在 lambda 内部调用该方法并在高阶函数中使用该方法。

我可以将这种做法与这种做法联系起来,因为我个人一般认为检查异常没有多大价值,但这是我不打算从这里开始的另一个完整的讨论。【关注尚硅谷,轻松学IT】如果您想将每个调用包装在一个签入 a 的 lambda 中 RuntimeException,您将看到您重复相同的模式。为了避免一遍又一遍地重写相同的代码,为什么不把它抽象成一个实用函数呢?这样,您只需编写一次并在每次需要时调用它。

为此,您首先需要为函数编写自己的功能接口版本。只有这一次,您需要定义该函数可能会抛出异常。

@FunctionalInterface
public interface CheckedFunction

{
R apply(T t) throws Exception;
}

现在,您已准备好编写自己的通用实用程序函数,该实用程序函数接受 CheckedFunction您刚刚在接口中描述的 a。您可以在此实用程序函数中处理 try-catch 并将原始异常包装到 a RuntimeException(或其他一些未经检查的变体)中。我知道我们现在在这里得到了一个丑陋的块 lambda,你可以从中抽象出身体。如果值得为这个单一实用程序付出努力,请自行选择。

public static

Function

wrap(CheckedFunction

checkedFunction) {
return t -> {
try {
return checkedFunction.apply(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}

通过简单的静态导入,您现在可以使用全新的实用程序函数包装可能引发异常的 lambda。从这一点开始,一切都会重新开始。

myList.stream()
.map(wrap(item -> doSomething(item)))
.forEach(System.out::println);

剩下的唯一问题是,当发生异常时,流的处理会立即停止。如果这对你来说没问题,那就去吧。但是,我可以想象,直接终止在许多情况下并不理想。

2任何一个

在处理流时,如果发生异常,我们可能不希望停止处理流。如果您的流包含大量需要处理的项目,您是否希望该流在第二个项目引发异常时终止?可能不是。

让我们换个思路。为什么不将“特殊情况”视为可能的结果,就像我们对“成功”结果的考虑一样。让我们将其视为数据,继续处理流,然后决定如何处理它。我们可以做到这一点,但要使其成为可能,我们需要引入一种新类型——Either 类型。

Either 类型是函数式语言中的一种常见类型,而不是(还)Java 的一部分。类似于 Java 中的 Optional 类型,an Either是具有两种可能性的通用包装器。它可以是左派或右派,但不能两者兼而有之。left 和 right 都可以是任何类型。例如,如果我们有一个 Either 值,则该值可以包含 String 类型或 Integer 类型的东西Either

如果我们使用这个原则来处理异常,我们可以说我们的 Either 类型要么持有一个值,要么持有 Exception一个值。为方便起见,通常左边是异常值,右边是成功值。你可以记住这一点,把右边不仅是右手边,而且是“好”、“好”等的同义词。

下面,您将看到该类型的基本实现 Either 。在这种情况下, Optional当我们尝试获取左侧或右侧时,我使用了该类型,因为我们:

public class Either

{
private final L left;
private final R right;
private Either(L left, R right) {
this.left = left;
this.right = right;
}
public static

Either

Left( L value) {
return new Either(value, null);
}
public static

Either

Right( R value) {
return new Either(null, value);
}
public Optional

getLeft() {
return Optional.ofNullable(left);
}
public Optional

getRight() {
return Optional.ofNullable(right);
}
public boolean isLeft() {
return left != null;
}
public boolean isRight() {
return right != null;
}
public

Optional

mapLeft(Function mapper) {
if (isLeft()) {
return Optional.of(mapper.apply(left));
}
return Optional.empty();
}
public

Optional

mapRight(Function mapper) {
if (isRight()) {
return Optional.of(mapper.apply(right));
}
return Optional.empty();
}
public String toString() {
if (isLeft()) {
return "Left(" + left +")";
}
return "Right(" + right +")";
}
}

您现在可以让自己的函数返回 an Either 而不是抛出 Exception. Exception 但是,如果您想使用在 lambda中抛出检查的现有方法,这对您没有帮助 吗?因此,我们必须在 Either 上面描述的类型中添加一个微小的效用函数。

public static

Function

lift(CheckedFunction

function) {
return t -> {
try {
return Either.Right(function.apply(t));
} catch (Exception ex) {
return Either.Left(ex);
}
};
}

通过将这个静态提升方法 添加到 Either. Either如果我们考虑最初的问题,我们现在会得到一个 Eithers 流,而不是可能 RuntimeException 会炸毁我的整个 Stream.

myList.stream()
.map(Either.lift(item -> doSomething(item)))
.forEach(System.out::println);

这仅仅意味着我们已经收回了控制权。通过使用 Stream APU 中的过滤器功能,我们可以简单地过滤掉左侧的实例,例如记录它们。【关注尚硅谷,轻松学IT】您还可以过滤正确的实例并简单地忽略异常情况。RuntimeException无论哪种方式,您都将重新获得控制权,并且当可能发生时,您的流不会立即终止 。

因为 Either 是一个泛型包装器,它可以用于任何类型,而不仅仅是用于异常处理。这使我们有机会做更多的事情,而不仅仅是将 包裹 Exception 到 Either. 我们现在可能遇到的问题是,如果 Either 唯一持有包装的异常,并且我们无法重试,因为我们丢失了原始值。通过使用 Either 保存任何东西的能力,我们可以将异常和值存储在 left 中。为此,我们只需像这样制作第二个静态提升函数。

public static

Function

liftWithValue(CheckedFunction

function) {
return t -> {
try {
return Either.Right(function.apply(t));
} catch (Exception ex) {
return Either.Left(Pair.of(ex,t));
}
};
}

您会看到,在此 liftWithValue 函数中, Pair 类型内用于将异常和原始值配对到 Either. 现在的左侧,如果出现问题,我们拥有我们可能需要的所有信息,而不是只有 Exception.

这里使用的 Pair 类型是另一种泛型类型,可以在 Apache Commons 语言库中找到,或者您可以简单地实现自己的。无论如何,它只是一个可以容纳两个值的类型。

public class Pair

{
public final F fst;
public final S snd;
private Pair(F fst, S snd) {
this.fst = fst;
this.snd = snd;
}
public static

Pair

of(F fst, S snd) {
return new Pair<>(fst,snd);
}
}

通过使用 liftWithValue,您现在拥有所有的灵活性和控制权来使用可能 Exception 在 lambda 中抛出的方法。当 Either 是正确时,我们知道该函数被正确应用并且我们可以提取结果。另一方面,如果 Either a 是左值,我们就知道出了问题,我们可以提取 theException和原始值,所以我们可以继续进行。通过使用 Either 类型而不是将 check 包装 Exception 到 a RuntimeException中,我们可以防止 Stream 中途终止。

3尝试

可能使用过 Scala 的人可能会使用 Scala Try而不是 Either异常处理。类型与 类型Try 非常相似 Either 。同样,它有两种情况:“成功”或“失败”。失败只能容纳类型 Exception,而成功可以容纳你想要的任何类型。因此,这 Try 只不过 Either 是左侧类型(失败)固定为 type 的特定实现Exception。

public class Try

{
private final Exception failure;
private final R succes;
public Try(Exception failure, R succes) {
this.failure = failure;
this.succes = succes;
}
}

有些人相信它更容易使用,但我认为因为我们只能 Exception在失败部分保持自身,所以我们遇到了与第一部分中解释的相同的问题 Either 。我个人更喜欢这种类型的灵活性 Either 。无论如何,在这两种情况下,如果您使用 Try 或 Either,您就解决了异常处理的初始问题,并且不要让您的流因 RuntimeException.

the Either 和 the Try 都很容易自己实现。另一方面,您还可以查看可用的功能库。例如,VAVR(以前称为 Javaslang)确实具有可用的类型和辅助函数的实现。我建议您看一下它,因为它的内容远不止这两种类型。www.atguigu.com 但是,您已经问自己一个问题,您是否希望这个大型库仅作为异常处理的依赖项,而您只需几行代码就可以自己实现它。

4结论

当你想使用一个抛出 a 的方法时, 如果你想在 lambda 中调用它checkedException,你必须做一些额外的事情。将其包装成一个 RuntimeException 可以使其工作的解决方案。try/catch 如果您更喜欢使用这种方法,我建议您创建一个简单的包装工具并重复使用它,这样您就不会被每次都打扰了。

如果你想拥有更多的控制权,你可以使用 Either or Try 类型来包装函数的结果,这样你就可以把它当作一条数据来处理。抛出a时流不会终止 RuntimeException ,您可以随意处理流中的数据。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
这些药物伤肝(新干货,收藏)!

这些药物伤肝(新干货,收藏)!

健康白皮书
2024-06-07 12:11:03
2008年,3岁男孩被拐3年,人群中一眼认出父亲,紧抱住父亲不松手

2008年,3岁男孩被拐3年,人群中一眼认出父亲,紧抱住父亲不松手

今天说故事
2024-04-22 17:22:03
国家消防局救援局:清查违规电动自行车势在必行!网友:车哪来的

国家消防局救援局:清查违规电动自行车势在必行!网友:车哪来的

棒棒糖画画
2024-06-07 23:38:08
短短24小时击落48架军机,1490人被就地消灭,急需征召十万大军

短短24小时击落48架军机,1490人被就地消灭,急需征召十万大军

军事在前沿
2024-06-07 11:52:57
三个数据:2024应届毕业生1179万,boss直聘新增用户4900万,深圳写字楼空置率30%

三个数据:2024应届毕业生1179万,boss直聘新增用户4900万,深圳写字楼空置率30%

西游日记
2024-06-05 08:59:06
消息称欧盟拟在匈牙利接任轮值主席国前 于本月正式启动乌克兰入盟谈判

消息称欧盟拟在匈牙利接任轮值主席国前 于本月正式启动乌克兰入盟谈判

财联社
2024-06-07 18:32:05
56分钟轰3球!马洛塔免签真香,1米97门将进入国米引援名单

56分钟轰3球!马洛塔免签真香,1米97门将进入国米引援名单

看懂帝国
2024-06-07 21:57:17
搞“两面派”、做“两面人”:金融“内鬼”徐翔被开除党籍

搞“两面派”、做“两面人”:金融“内鬼”徐翔被开除党籍

澎湃新闻
2024-06-07 16:44:26
太神了!语文老师押中高考作文登上热搜!评论区考生却炸锅!

太神了!语文老师押中高考作文登上热搜!评论区考生却炸锅!

请叫我教育君
2024-06-08 04:45:52
一出一进!法媒史诗级建议:巴黎反掏1.5亿,第2次挖皇马核心

一出一进!法媒史诗级建议:巴黎反掏1.5亿,第2次挖皇马核心

叁炮体育
2024-06-07 12:14:54
军援俄罗斯

军援俄罗斯

求实处
2024-04-30 21:30:03
只差40分!詹姆斯就将创造历史第一纪录,前无古人后无来者

只差40分!詹姆斯就将创造历史第一纪录,前无古人后无来者

轻乐娱评甲
2024-06-07 16:53:47
足坛疯狂夜:格10落选成炸弹 英格兰不敌39万小国 德国2-1神逆转

足坛疯狂夜:格10落选成炸弹 英格兰不敌39万小国 德国2-1神逆转

狍子歪解体坛
2024-06-08 04:47:12
阿里纳斯:科比曾和训练师争吵 因为后者防守时不如拉加-贝尔凶狠

阿里纳斯:科比曾和训练师争吵 因为后者防守时不如拉加-贝尔凶狠

直播吧
2024-06-07 22:40:08
日内跌超60美元!黄金价格跳水,白银也大跌超5%!连增18个月后央行暂停增持黄金,美联储降息有变?

日内跌超60美元!黄金价格跳水,白银也大跌超5%!连增18个月后央行暂停增持黄金,美联储降息有变?

每日经济新闻
2024-06-07 22:58:04
哈文:陪读生活结束后,回国后就立马带女儿到上海拜访王冠

哈文:陪读生活结束后,回国后就立马带女儿到上海拜访王冠

麦香娱综艺
2024-06-07 18:10:38
刚解禁1天,武磊却伤了,报到10天无法训练,中国队3大前锋受损

刚解禁1天,武磊却伤了,报到10天无法训练,中国队3大前锋受损

北门儿
2024-06-07 18:02:06
孙卓迎来高考,孙海洋表示不会穿旗袍陪考,一家五口同框叫人破防

孙卓迎来高考,孙海洋表示不会穿旗袍陪考,一家五口同框叫人破防

阿蒙聊教育
2024-06-06 22:49:52
体育总局出手 中国女排主教练首次公开认错担责 蔡斌五点声明解析

体育总局出手 中国女排主教练首次公开认错担责 蔡斌五点声明解析

排球评论员
2024-06-07 18:05:27
实体店倒闭潮来了,电商倒闭潮也来了,到底谁在闷声发大财

实体店倒闭潮来了,电商倒闭潮也来了,到底谁在闷声发大财

互联共商
2024-06-08 05:34:14
2024-06-08 07:40:49
IT爱好者小尚
IT爱好者小尚
分享IT教育类信息
630文章数 55关注度
往期回顾 全部

科技要闻

6家大模型抢答高考作文,谁是你心中的Top1

头条要闻

媒体:马克龙援乌战机祭出"大杀器" 发出十分危险信号

头条要闻

媒体:马克龙援乌战机祭出"大杀器" 发出十分危险信号

体育要闻

优势在我?中国足球有自己的节奏

娱乐要闻

汤唯抵达巴黎将担任奥运火炬手

财经要闻

身陷退市股的投资者:我的钱瞬间没了

汽车要闻

2.0T混动售20.98万元起 福特蒙迪欧运动版上市

态度原创

游戏
旅游
时尚
家居
手机

舅舅党再爆猛料,魔兽世界正式服七月份有望开服,你还会回归吗?

旅游要闻

上海迪士尼年卡最高档位卡种八折优惠改为满减

接下来几个月,比看赛事更有意思的是......

家居要闻

柔和婉转 让阳光洒满空间

手机要闻

传骁龙8 Gen4 Adreno 830 GPU将采用改进的内存压缩算法以提高利用率和性能

无障碍浏览 进入关怀版