我正在教授关于新Java构造的课程。我已经向Optional<T>
介绍了我的学生。设想有Point.getQuadrant()
返回Optional<Quadrant>
(因为有些点根本没有象限),如果该点位于正X,我们可以将象限添加到Set<Quadrant>
象限,像这样:
Set<Quadrant> quadrants = ...;
Optional<Point> point = ...;
point
.filter(p -> p.getX() > 0)
.flatMap(Point::getQuadrant)
.ifPresent(quadrants::add);
(这是我的头脑;如果我犯了错误,请告诉我。)
我的下一步是告诉我的学生,“如果你能使用函数进行相同的内部过滤和决策,但是使用多个对象,这不是很好吗?这就是溪流的用途!”这似乎是完美的segue。我几乎已经准备好使用流来写出相同的表单,但是带有 list 点数:
Set<Point> points = ...;
Set<Quadrant> quadrants = points.stream()
.filter(p -> p.getX() > 0)
.flatMap(Point::getQuadrant)
.collect(Collectors.toSet());
但是等等! Stream.flatMap(Point::getQuadrant)
会正确解开Optional<Quadrant>
吗?看来不是......
我已经读过Using Java 8's Optional with Stream::flatMap,但我原以为在那里讨论的是一些深奥的一面,并没有真实的相关性。但是现在我正在玩它,我发现这与我们做的大多数事情直接相关。
简单地说,如果Java现在希望我们使用Optional<T>
作为新的可选返回习语;如果Java现在鼓励我们使用流来处理我们的对象,那么我们不期望在整个地方遇到映射到可选值吗?我们是否真的必须跳过一系列.filter(Optional::isPresent).map(Optional::get)
箍作为解决方法,直到Java 9从现在起几年后到达这里?
我希望我只是误解了另一个问题,我只是误解了一些简单的事情,而且有人可以让我直截了当。当然Java 8没有这么大的盲点,是吗?
答案 0 :(得分:1)
我不确定你的问题在哪里。链接问题的答案已经表明, 是Java 8中的一个缺陷,因此在Java 9中解决这个问题。因此,在Java 8中确定这是否真的是一个缺陷是没有意义的。
除此之外,答案还提到.flatMap(o -> o.isPresent()? Stream.of(o.get()): Stream.empty())
用于转换可选项,而不是.filter(Optional::isPresent) .map(Optional::get)
。不过,你可以做得更简单:
而不是
.flatMap(Point::getQuadrant)
你可以写
.flatMap(p -> p.getQuadrant().map(Stream::of).orElse(null))
作为Java 9的替代
.flatMap(p -> p.getQuadrant().stream())
请注意
.map(Point::getQuadrant).flatMap(Optional::stream)
与替代方案相比并没有那么好,除非你对方法引用有一种非理性的亲和力。