可选与Java Stream不兼容?

时间:2016-05-06 23:52:12

标签: java java-stream optional

我正在教授关于新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没有这么大的盲点,是吗?

1 个答案:

答案 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)

与替代方案相比并没有那么好,除非你对方法引用有一种非理性的亲和力。