在JDK 9(以及8)以及更高版本中,所有内容都可以作为一个流

在JDK 8中,我们终于可以使用流了,除了您使用的API无法产生流的时代之外,其他一切都很好。 然后,您最终编写了一个包装器类方法,该方法允许您将迭代器转换为Stream,因为您错过了流。

public static <T> Stream<T> asStream(Iterator<T> it) {
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,
        Spliterator.IMMUTABLE | Spliterator.ORDERED),false);
}

现在有一些方法可以在迭代生成的情况下以编程方式生成流,但是这两种方法都会生成无限流,而在大多数情况下,您确实想将现有接口改编为有限流。

在JDK 9中,通过引入一种新形式的迭代方法很好地解决了该问题,该方法允许您提供一个谓词来表示流的结束。

在下面的示例中,我将使用谓词,该谓词将一直持续到您获得流的空条目为止,然后由读者自己来提出谓词的更多想象力。 在这个简单的示例中,我使用Throwable的getCause方法使我们沿着错误的链接列表移动。 请注意,与预发布版本相比,这将花费很少的代码。

// Simple linked list
//
Exception e = new Exception("one");
Exception e2 = new Exception("two",e);
Exception e3 = new Exception("three", e2);

Stream.iterate(e3, Objects::nonNull, Throwable::getCause)

    // Output the messages in turn
    .map(Throwable::getMessage)
    .forEach(System.out::println);

第二个示例将ReferenceQueue转换为Stream,以便我们可以轻松地耗尽其内容以根据需要进行处理。 这段代码有些不同,因为容器与要处理的对象不同,因此我们使用相同的方法提供种子和下一个值,当队列为空时,它返回null。

ReferenceQueue<Thing> queue = new ReferenceQueue<>();

// Make some things and then collect them
WeakReference one = new WeakReference<Thing>(new Thing(), queue);
WeakReference two = new WeakReference<Thing>(new Thing(), queue);
System.gc(); System.gc(); System.gc(); System.gc(); System.gc();

Stream.<Reference<? extends Thing>>iterate(
    queue.poll(), Objects::nonNull, v -> queue.poll())


    .forEach(System.out::println);

第三个示例显示了如何在Node树上行走,请注意,当我们工作到叶子的末尾时,嵌套的流迭代器将备份列表。

Node root = doc.getDocumentElement();

Stream.iterate(
    root,
    Objects::nonNull,
    v -> {
        if (v.getFirstChild()!=null) {
            return v.getFirstChild();
        }

        if (v.getNextSibling()!=null) {
            return v.getNextSibling();
        }

        return Stream.iterate(v, Objects::nonNull, Node::getParentNode)
            .filter(node -> node.getNextSibling()!=null)
            .map(Node::getNextSibling).findFirst().orElse(null);
    })

    .map(Node::getNodeName)
    .forEach(System.out::println);

因此,通过进行少量的心理操练,就可以将大多数旧版API转换为干净的Stream,因此您可以忽略那些讨厌的老式循环。 而且,如果您陷于JDK 8中,那么很容易使用之前的asStream来组合类似的功能:

public static<T> Stream<T> iterateFinite(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next) {

    return asStream(new Iterator<>() {

        T current = seed;

        @Override
        public boolean hasNext() {
            return hasNext.test(current);
        }

        @Override
        public T next() {
            if (current == null) {
                throw new NoSuchElementException();
            }
            try {
                return current;
            } finally {
                current = next.apply(current);
            }
        }
    });
}

翻译自: https://www.javacodegeeks.com/2018/12/jdk-9-everything-can-stream.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值