【问题标题】:Java-8: boolean primitive array to stream?Java-8:要流式传输的布尔原始数组?
【发布时间】:2017-02-14 11:30:05
【问题描述】:

没有很好的方法将给定的boolean[] foo 数组转换为 Java-8 中的流在一个语句中,或者我遗漏了什么?

(我不会问为什么?,但这真的很令人费解:为什么不为所有原始类型添​​加流支持?)

提示: Arrays.stream(foo) 不起作用,boolean[] 类型没有这种方法。

【问题讨论】:

  • 确实,Java 8 只为intlongdouble 提供了专门的原始流,而Arrays.stream 不接受boolean[]。我想你必须把它装箱。
  • 在这里使用BitSet 会比使用数组更有用吗?
  • @Fildor:是的,您可以对位集进行流操作。但是,结果可能会有所不同,因为您正在流式传输这些位(即它们的位置编号)。令人惊讶的是,障碍在另一边:没有简洁的方法可以将boolean[] 数组转换为BitSet
  • 希望,链接的问答仍然有帮助。创建BooleanStream 也意味着创建PrimitiveIterator.OfBooleanOptionalBooleanBooleanFunction<T>BooleanPredicate(或者我们为此滥用BooleanUnaryFunction?)、BooleanBinaryOperatorBooleanToIntFunctionBooleanToLongFunctionBooleanToDoubleFunctionBooleanConsumer、(不知什么原因,存在BooleanSupplier)、ObjBooleanConsumerBooleanSummaryStatistics
  • @Holger,BooleanSupplier 完成了(Object|int|long|double|void) -> (Object|int|long|double|void|boolean) 函数的矩阵:所有这 30 个函数实际上都存在于 JDK 中,并且似乎没有提供其他一/零参数函数。所以BooleanSupplier 看起来很合理。

标签: java java-8 java-stream


【解决方案1】:

给定boolean[] foo 使用

Stream<Boolean> stream = IntStream.range(0, foo.length)
                                  .mapToObj(idx -> foo[idx]);

请注意,每个布尔值都会被装箱,但这通常不是什么大问题,因为布尔值装箱不会分配额外的内存(只使用预定义值之一 - Boolean.TRUEBoolean.FALSE)。

【讨论】:

  • 在您看来,是否可以安全地推断booleans 上的“轻量级”装箱操作可能是booleans 没有专门的原始流的原因?
  • 不错的一个+1,让我们看看,可能会有其他想法进入人们的脑海:)
  • @Mena,有多种原因。其中之一是代码爆炸:每个原始流都添加了大量的专用代码,更不用说添加IntStream.mapToBooleanBooleanStream.mapToDouble 等时的二次API 增长。所以他们不得不在某个地方停下来。他们认为intlongdouble 是最有用的原始类型,所以这是一个合理的权衡。希望 Java 10 能给我们带来通用的专业化,Stream&lt;boolean&gt; 可以开箱即用。
  • 尽可能关闭,我猜。但是“好”是不同的-恕我直言。 (+1)
  • @TagirValeev 他们本可以停在......所有的原语,没有那么多(8个原语+ 1个参考)。
【解决方案2】:

你可以使用Guava's Booleans class:

Stream<Boolean> stream = Booleans.asList(foo).stream();

这是一种非常有效的方法,因为Booleans.asList 返回数组的包装器并且不进行任何复制。

【讨论】:

  • 不错!请注意,除非定义了自定义拆分器(并且它是 not defined,否则结果流不会是 SIZED。这可能会影响某些操作的性能,例如 toArray()。它也不会很好地并行化(如果有人关心的话)。
  • @Tagir Valeev:default spliterator of List“报告 Spliterator.SIZED 和 Spliterator.ORDERED”…
  • @TagirValeev 我刚刚检查了Booleans.asList() 返回的拆分器的特征,看起来它具有 SIZED 特征。
  • @Holger,对不起,我的错。那么唯一的问题是并行性。虽然它也是 Java-9 中的 addressed
  • @ZhekaKozlov, nope, spliterator trySplit() 方法必须正确实现。默认是“穷人并行”,它通过迭代器顺序遍历列表到中间缓冲区
【解决方案3】:

当然你可以直接创建一个流

Stream.Builder<Boolean> builder = Stream.builder();
for (int i = 0; i < foo.length; i++)
  builder.add(foo[i]);
Stream<Boolean> stream = builder.build();

...或者通过包装一个 AbstractList around foo

Stream<Boolean> stream = new AbstractList<Boolean>() {
  public Boolean get(int index) {return (foo[index]);}
  public int size() {return foo.length;}
}.stream();

【讨论】:

  • 这是三个顶级语句 + for 内的三个语句表达式。 ,_________,
  • @Andrey 我没有用另一种方式表达的短语。 直接的意思是手工一块一块地组装起来。我希望你喜欢第二个解决方案。
【解决方案4】:

浏览最新的 的早期访问JavaDoc(即java.base 模块),仍然没有巧妙的方法来使原始布尔数组与 Stream API 一起工作。自 以来,API 中没有新功能处理原始布尔数组。

请注意,存在 IntStreamDoubleStreamLongStream,但没有像 BooleanStream 那样表示原始布尔序列的变体。 Stream的重载方法还有Stream::mapToIntStream::mapToDoubleStream::mapToLong,但不是Stream::mapToBoolean返回这样的假设BooleanStream

Oracle 似乎一直遵循这种模式,这也可以在 Collectors 中找到。也没有对float 原语的这种支持(有double 原语)。在我看来,与float 不同的是,boolean 的支持是有意义的。

回到代码...如果你有一个装箱的布尔数组(即Boolean[] array),事情会变得更容易:

Boolean[] array = ...
Stream<Boolean> streamOfBoxedBoolean1 = Arrays.stream(array);
Stream<Boolean> streamOfBoxedBoolean2 = Stream.of(array);

否则,您必须使用多个语句,如thisthis 答案中所述。

但是,你问(强调我的):

one 语句中将给定的boolean[] foo 数组转换为 Java-8 中的流的方法。

...实际上有一种方法可以通过一个语句使用由Iterator 制成的Spliterator 来实现此目的。这绝对不是很好,但是:

boolean[] array = ...

Stream<Boolean> stream = StreamSupport.stream(
        Spliterators.spliteratorUnknownSize(
                new Iterator<>() {
                    int index = 0;
                    @Override public boolean hasNext() { return index < array.length; }
                    @Override public Boolean next() { return array[index++]; }
                }, 0), false);

【讨论】:

    猜你喜欢
    • 2021-04-08
    • 2023-03-18
    • 1970-01-01
    • 2011-08-02
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多