【问题标题】:Iterator in reverse - for reduceRight functionality反向迭代器 - 用于 reduceRight 功能
【发布时间】:2019-07-10 21:19:03
【问题描述】:

尝试实现一些 reduceRight 功能。 对于性能来说,从右到左迭代会很好,而不是先反转所有内容,然后再从左到右。通常我们会这样做:

Iteratable iterable ...;
Iterator iterator = iterable.iterator();
iterator.next();

但我正在寻找类似的东西:

Iteratable iterable ...;
Iterator iterator = iterable.reverseIterator();
iterator.next();

我看到了这个解决方案:Iterating through a list in reverse order in java

当前接受的答案表明这是可行的:

ArrayList<...> a = new ArrayList<...>();

// Add elements to list.

// Generate an iterator. Start just after the last element.
ListIterator li = a.listIterator(a.size());

// Iterate in reverse.
while(li.hasPrevious()) {
  System.out.println(li.previous());
}

任何人都知道如何在手头只有Iterable 的情况下实现反向迭代吗?我手头没有ArrayList 或列表,我手头有Iterable。我想我可以将 Iterable 转换为 ArrayList,反转列表,然后得到一个迭代器,但这并不有趣 :)

【问题讨论】:

  • 你不能。迭代器只支持单向遍历。您必须将元素复制到堆栈并弹出它们。鉴于您正在努力实现性能,我不会这样做 - 看看您是否可以在另一个方向上重新表达您的 reduce。
  • @BoristheSpider 是的,这就是我的想法,鉴于 OP 中的信息,您能否提供最佳解决方案?谢谢
  • 请记住,Iterable 在理论上可以是无限的。这就是为什么在 API 级别不支持此功能的原因。您应该使用支持反向遍历的数据结构。
  • @JoeC 这是一个库,因此尝试使用Iterable支持尽可能多的数据类型
  • @JoeC 的观点值得牢记——StreamIterator 都可以是无限的;以Guava's Iterators.cycle 为例。我会避免公开允许您无法支持的内容的 API。

标签: java iterator iterable


【解决方案1】:

简单的答案:不可能以通用的高性能方式。

迭代器的本质是让你一个方向,而不是两个。并想象一个单链表。那玩意真的“只有一个方向”!

因此,如何反转可迭代事物的问题确实需要您查看确切的实现。 如果没有这种可能性,您必须在反转之前使用中间数据结构来获取所有条目。

【讨论】:

    【解决方案2】:

    您必须对原始Iterator 进行一次迭代才能构造一个反向的Iterator(假设您的原始Iterator 是有限的)。

    例如:

    static <T> Iterator<T> getReversedIterator(Iterable<T> iterable) {
        Iterator<T> iter = iterable.iterator();
        List<T> rev = new ArrayList<>();
        while (iter.hasNext()) {
            rev.add (0, iter.next());
        }
        return rev.iterator();
    }
    

    【讨论】:

      【解决方案3】:

      如果您手头有Iterable,正如您在问题中所写,那么有人为您提供了它。我建议要求提供者提供支持反向迭代的Iterable

      【讨论】:

      • 那或者只是实现 reduce 而不要实现 reduceRight 并期望他们以正确的顺序排列列表。但我认为为 lib 的用户做这项工作很好。
      【解决方案4】:

      这是我的做法。如果您使用的是 for 循环,这将导致原始迭代器被完全消耗,并在第一次迭代之前创建一个新的链表。这显然是大型迭代的问题,但它是可预测且易于使用的。与一些仅适用于特定类型的解决方案相比,它具有适用于任何实现 Iterable 的解决方案的优势。

      import java.util.Iterator;
      
      public class Reversible<E> implements Iterable<E> {
          private Iterable<E> source;
      
          public Reversible(Iterable<E> source) {
              this.source = source;
          }
      
          public Iterator<E> iterator() {
              return new Reverserator<>(source.iterator());
          }
      
          public static class Reverserator<E> implements Iterator<E> {
              private Entry<E> next = null;
      
              private Reverserator(Iterator<E> source) {
                  while (source.hasNext()) {
                      next = new Entry<>(source.next(), next);
                  }
              }
      
              public boolean hasNext() {
                  return next != null;
              }
      
              public E next() {
                  Entry<E> curr = next;
                  next = curr.next;
                  return curr.obj;
              }
      
              private static class Entry<E> {
                  private E obj;
                  private Entry<E> next;
      
                  private Entry(E obj, Entry<E> next) {
                      this.obj = obj;
                      this.next = next;
                  }
              }
          }
      }
      

      使用起来非常简单:

      List<String> names = new ArrayList<>();
      names.add("George");
      names.add("Fred");
      names.add("Harry");
      for (String name:new Reversible<>(names)) {
          System.out.println(name);
      }
      

      返回:

      Harry
      Fred
      George
      

      【讨论】:

        猜你喜欢
        • 2010-10-27
        • 1970-01-01
        • 2019-12-06
        • 1970-01-01
        • 2021-11-27
        • 1970-01-01
        • 1970-01-01
        • 2014-09-15
        • 1970-01-01
        相关资源
        最近更新 更多