通过排序集合成对迭代的成语

时间:2013-07-03 16:12:17

标签: java collections

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

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

 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),按此顺序。

5 个答案:

答案 0 :(得分: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;
    }
}

答案 1 :(得分: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;
}

答案 2 :(得分: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 ...
}

答案 3 :(得分:0)

对于Set s(以及其他不可索引的集合),您需要使用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; } 方法返回的Iterator

Map

您可以使用iterator()IteratorIterator<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); } 执行相同操作。


既然我更了解你的问题,你也可以试试这个:

{{1}}

答案 4 :(得分: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());
    }
}

也许,当循环代码变得更加复杂时,好处就会更加明显。