代码之家  ›  专栏  ›  技术社区  ›  BlondMammuth

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

  •  5
  • BlondMammuth  · 技术社区  · 7 年前

    Iterable<Integer> 并获得基元迭代器。OFIT,将其提供给另一个函数,该函数构造另一个迭代器(即,这些函数旨在以各种方式组成迭代器)。

    下面是一个简单的例子来说明我的想法:

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

    iterator Iterable<整数> 对象可能不是类型 PrimitiveIterator.OfInt

    PrimitiveIterable.OfInt 或者任何其他方法来确定迭代器是否实际上是基元的。我已经搜索了很长一段时间,但通常只是浏览我几乎所有问题的答案,这次我不得不在这里注册直接问那个问题。

    这种构造旨在避免装箱/拆箱狂欢,因为我希望新的迭代器速度相当快。

    1. 有没有办法确定从iterable获得的迭代器实际上是否是原始迭代器(这样函数就可以进行区分并相应地执行操作) 有没有其他方法可以获得一个?
    2. 这样提高性能可能没有用吗?一、 (JIT或Java)编译器是否会优化这一点,或者装箱/拆箱是否不可避免?在这里我希望学到一些东西。

    更新: next() 在一个 PrimitiveInteger.OfInt ,这会调用 nextInt() 方法,或者换句话说:这会自动返回纯 int

    nextInt()

    instanceof 方法,并在需要时显式换行。

    1 回复  |  直到 7 年前
        1
  •  4
  •   Community SushiHangover    4 年前

    好吧,你可以简单地使用 iterator instanceof PrimitiveIterator.OfInt 测试,但当预期操作 forEachRemaining IntConsumer 将传递给 PrimitiveIterator.OfInt 为了高效处理和 Consumer<Integer> 基本迭代器。OFIT 如果你在一个类中实现了这两个,你根本不需要执行测试,迭代器会帮你:

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

    这不适用于通过 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);
    }
    

    但请注意,这个迭代器组合看起来非常像流API(或 IntStream