【问题标题】:Create Java 8 Stream from ArrayNode从 ArrayNode 创建 Java 8 流
【发布时间】:2015-09-20 20:07:22
【问题描述】:

是否可以从com.fasterxml.jackson.databind.node.ArrayNode 创建流?
我试过了:

ArrayNode files = (ArrayNode) json.get("files");
Stream<JsonNode> stream = Stream.of(files);

但它实际上会给出一个元素的流,即初始 ArrayNode 对象。
正确的结果应该是Stream&lt;JsonNode&gt;,可以实现吗?

【问题讨论】:

  • 这里的整个数组会被加载到内存中吗?我相信答案是“是”。那么在这里有一个流有什么意义呢?
  • @AndreyKarayvansky 这不是关于性能,而是关于使用Java 8 Stream API 方法以“功能方式”处理ArrayNode 集合的能力(使用mapfiltercollect 等方法...)。
  • Lists.newArrayList(arrayNode.elements()).stream() //by Guava

标签: jackson java-8 java-stream fasterxml


【解决方案1】:

ArrayNode 实现Iterable。 Iterable 有一个spliterator() 方法。你可以create a sequential Stream from a Spliterator使用

ArrayNode arrayNode = (ArrayNode) json.get("xyz");
StreamSupport.stream(arrayNode.spliterator(), false)

【讨论】:

  • 我尝试了您的解决方案并且它有效,但我不明白为什么 Stream.of(files) 没有,而 spliterator 没有。
  • 因为 Stream.of() 需要一个数组作为参数,而 ArrayNode 不是数组。
【解决方案2】:

ArrayNode 类提供随机访问:您可以通过索引获取size() 和一个元素(使用get(index))。这就是创建良好流所需的全部内容:

Stream<JsonNode> nodes = IntStream.range(0, files.size()).mapToObj(files::get);

请注意,此解决方案比使用默认拆分器(如其他回答者所建议的那样)更好,因为它可以很好地拆分并正确报告大小。即使您不关心并行处理,像toArray() 这样的一些操作也会更有效地工作,因为提前知道大小将有助于分配适当大小的数组。

【讨论】:

  • 我同意你所说的一切,这在很多方面都是更好的解决方案。但我希望直接在ArrayNode 类或某些Utils 方法中看到这样的解决方案。流应该使代码更易于阅读和理解。将此解决方案用于简单的 filter-map-collect 操作会稍微增加代码的复杂性。无论如何,非常好的想法,你得到了我的 +1。
  • @klerik,在保持 Java-8 之前的兼容性的同时提供流 API 方法并不容易。
  • 我喜欢这个,因为这意味着我也不必将我的 JsonNode 转换为 ArrayNode
【解决方案3】:

ArrayNode#elements 在它的元素上返回一个迭代器,您可以使用它来创建一个流(通过利用 StreamSupport)。 StreamSupport 需要 Spliterator,要从 Iterator 创建 Spliterator,您可以使用 Spliterators 类。

  ArrayNode files = (ArrayNode) json.get("files");
  Stream<JsonNode>  elementStream = StreamSupport.stream(Spliterators
                  .spliteratorUnknownSize(files.elements(),
                        Spliterator.ORDERED),false);

cyclops-streams 有一个 StreamUtils 类有一个静态方法,这使得它更干净一些(我是作者)。

 ArrayNode files = (ArrayNode) json.get("files");
 Stream<JsonNode>  elementStream = StreamUtils.stream(files.elements());

考虑到@JB Nizet 的回答,即 ArrayNode 是 StreamUtils 的可迭代对象,您可以传入 ArrayNode 并直接取回 Stream。

Stream<JsonNode>  elementStream = StreamUtils.stream((ArrayNode) json.get("files"));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 2017-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多