5

是否有通过 sorted 的元素进行成对迭代的 Java 习惯用法Collection?我的意思是每次迭代都可以访问集合的一个元素和集合的下一个元素?

对于排序List的 s(和数组),可以使用集合中的索引来完成:

 final int n = list.size();
 assert 2 <= n;
 for (int i = 0; i < n - 1; ++i) {
    final Thing thing1 = list.get(i);
    final Thing thing2 = list.get(i+1);
    operateOnAdjacentPair(thing1, thing2);
 }

但是呢SortedSet?(因为SortedMap您可以使用它的entrySet(),这相当于SortedSet案例)。


因此,例如,如果您的排序集包含值 {1, 2, 3, 4},则迭代将按顺序对 (1, 2), (2, 3), (3, 4) .

4

5 回答 5

5
Iterator<Thing> thingerator = coll.iterator();
if (thingerator.hasNext()) {
    Thing thing1 = thingerator.next();
    while (thingerator.hasNext()) {
      final Thing thing2 = thingerator.next();
      doStuffToThings(thing1, thing2);

      thing1 = thing2;
    }
}
于 2013-07-03T16:16:54.560 回答
3

您可以通过以下方式简单地实现它(并对其他集合应用类似的策略):

Iterator<Thing> iter = set.iterator();
Thing previous = iter.hasNext() ? iter.next() : null;
while (iter.hasNext()) {
    final Thing current = iter.next();
    operateOnAdjacentPair(previous, current);
    previous = current;
}
于 2013-07-03T21:02:01.340 回答
1

编写一个迭代器的实现,例如(只是在我的脑海中写下,所以代码可能无法按原样工作)

public class PairwiseIterator<T> implements Iterator<List<T>> {
    private final Iterator<T> elements;
    private T last;

    public PairwiseIterator(Collection<T> elements) {
        this.elements = elements.iterator();
        last = elements.hasNext() ? elements.next() : null;
    }

    @Override
    public boolean hasNext() {
        return elements.hasNext();
    }

    @Override
    public List<T> next() {
        List<T> result = ImmutableList.of(last, elements.next());
        last = result.get(1);
        return result;
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException("Remove not allowed with this iterator");
    }

    public static <U> Iterable<List<U>> iterable(final Collection<U> elements) {
        return new Iterable() {
            public Iterator<U> iterator() {
                return new PairwiseIterator(elements);
            }
        }
    }
}

我可能没有完全正确的类型,但是 'iterable' 方法使它很容易在 foreach 构造中使用:

for(List<String> pair : PairwiseIterator.iterable(orderedSetOfStrings)) {
    // ... do what you need to ...
}
于 2014-07-09T18:20:52.957 回答
0

对于Sets (和其他不可索引的集合),您将需要使用方法Iterator返回的 s :iterator()Collection

Iterator<Thing> iter = set.iterator();
Thing thing1 = iter.next();  // might want to check if this exists
while (iter.hasNext()) {
    Thing thing2 = iter.next();
    operateOnAdjacentPair(thing1, thing2);
    thing1 = thing2;
}

你可以对Maps 做同样的事情,使用Iterator他们entrySet()的 s。


现在我更好地理解了你的问题,你也可以试试这个:

Iterator<Thing> iter1 = set.iterator(), iter2 = set.iterator();

if (iter2.hasNext())
    iter2.next();  // burn first element

while (iter2.hasNext()) {
    final Thing thing1 = iter1.next();
    final Thing thing2 = iter2.next();
    operateOnAdjacentPair(thing1, thing2);
}
于 2013-07-03T16:17:07.593 回答
0

Guava 提供了一个可用于此目的的 PeekingIterator:

PeekingIterator<Thing> iter = 
    Iterators.peekingIterator(set.iterator());
while (iter.hasNext()) {
    final Thing thing1 = iter.next();
   if (iter.hasNext()) { // don't forget this one
        operateOnAdjacentPair(thing1, iter.peek());
    }
}

当循环代码变得更复杂时,好处可能会变得更加明显。

于 2019-06-11T09:02:40.217 回答