Java 8 中的方法是否可以简单地确定 Iterable<Integer> 对象是否提供 PrimitiveIterator.OfInt 迭代器?

Is it possible for a method in Java 8 to determine simply whether an Iterable<Integer> Object provides a PrimitiveIterator.OfInt iterator?

这是我第一次activity来这里,希望我的举止端正!我的问题:我正在尝试编写一组函数(class 中的静态方法)接受一个或多个 Iterable<Integer> 并获得 primitiveIterator.ofInt,将其提供给另一个构造函数另一个迭代器(即函数旨在以各种方式组合迭代器)。

这是我的想法的一个简单示例:

public static FilterIteratorInt filtor(Iterable<Integer> iter, IntPredicate filter)
{
    return new FilterIteratorInt((PrimitiveIterator.OfInt)iter.iterator(),filter);
}   

对我来说,我不太清楚这是否可行,因为 Iterable<Integer> 对象返回的 iterator 可能不是 PrimitiveIterator.OfInt.[=25 类型=]

为了克服这个潜在的困难,我一直在寻找一个解决方案,它可能是一个接口,例如PrimitiveIterable.OfInt 或任何其他方式来确定迭代器是否实际上是原始的。我已经搜索了很长时间,虽然通常只是浏览几乎所有问题的答案,但这次我必须在这里注册才能直接提问。

这个构造是为了避免 boxing/unboxing 狂欢,因为我希望新的迭代器相当快。

所以这里有三个问题:

  1. 有没有办法找出从可迭代对象中获得的迭代器是否实际上是原始迭代器(这样函数就可以区分并相应地采取行动)还有另一个获取途径?
  2. 这样尝试提高性能可能没有用吗? IE。无论如何,(JIT 或 Java)编译器都会对此进行优化,还是 boxing/unboxing 无论如何都不可避免?在这里希望能有所收获。
  3. 谁能告诉我一个不同的更好的解决方案,可以达到相同的目的(即原始迭代器或任何迭代器的组合,而我们正在这样做)?

更新: 由于 Holgers 的回答,归结为以下问题 nr。 4:如果在 PrimitiveInteger.OfInt 上调用 next(),这是否会调用 nextInt() 方法,或者换句话说:这会自动返回纯 int 吗?或者它仍然会导致装箱和拆箱序列?

根据下面的答案,我假设是后者,这意味着明确地处理 nextInt() 肯定更好。

假设这是正确的(如果我错了请告诉我),我使用了下面的 instanceof 方法并在需要时显式换行。

嗯,你可以简单地使用 iterator instanceof PrimitiveIterator.OfInt 来测试,但是当预期的操作是 forEachRemaining 时,你将需要两者,一个 IntConsumer 传递给 PrimitiveIterator.OfInt 用于高效处理,Consumer<Integer> 用于处理那些不是 PrimitiveIterator.OfInt 实例的迭代器,如果您在一个 class 中实现这两者,则根本不需要执行测试,迭代器将为您完成:

public static void main(String[] args) {
    System.out.println("with Collection (of Integer boxes)");
    filterAndPrint(Arrays.asList(1, 2, 3), i -> i>2);
    System.out.println("with IntStream (using primitive int values)");
    filterAndPrint(() -> IntStream.range(1, 4).iterator(), i -> i>2);
}
interface LoggingUnboxingIntConsumer extends IntConsumer, Consumer<Integer> {
    @Override default void accept(Integer t) {
        System.out.println("  unboxing " + t);
            accept(t.intValue());
    }
}
public static void filterAndPrint(Iterable<Integer> i, IntPredicate p) {
    i.iterator().forEachRemaining((LoggingUnboxingIntConsumer) (int value) -> {
        if(p.test(value)) System.out.println("  value "+value+" matches");
    });
}
with Collection (of Integer boxes)
  unboxing 1
  unboxing 2
  unboxing 3
  value 3 matches
with IntStream (using primitive int values)
  value 3 matches

这表明尽可能避免装箱操作。这是 the contract of PrimitiveIterator.OfInt.forEachRemaining(Consumer<? super Integer>) 的一部分:

Implementation Requirements:

If the action is an instance of IntConsumer then it is cast to IntConsumer and passed to forEachRemaining(java.util.function.IntConsumer); otherwise the action is adapted to an instance of IntConsumer, by boxing the argument of IntConsumer, and then passed to forEachRemaining(java.util.function.IntConsumer).

这不适用于通过 hasNext()/next() 进行的单个元素处理,但由于您的代码应该仅执行 PrimitiveIterable.OfInt 的组合,因此初始步骤是唯一的地方无论如何都必须进行适应

public static PrimitiveIterator.OfInt adapt(Iterator<Integer> it) {
    return it instanceof PrimitiveIterator.OfInt? (PrimitiveIterator.OfInt)it:
      new PrimitiveIterator.OfInt() {
        public int nextInt() { return it.next(); }
        public boolean hasNext() { return it.hasNext(); }
        public Integer next() { return it.next(); }
      };
}

创建此方法一次后,您可以在所有接受 Iterable 的地方使用它,例如

public static FilterIteratorInt filter(Iterable<Integer> iter, IntPredicate filter) {
    return new FilterIteratorInt(adapt(iter.iterator()), filter);
}

但请注意,这个“迭代器组合”看起来非常像对 Stream API(或 IntStream API 具体而言)的重新发明...