Java – 迭代列表中的每两个元素

在同时处理2个元素的同时迭代列表的最佳方法是什么?

例:

List strings = Arrays.asList("item 1", "item 2", "item 3", "item 4"); for(int i = 0; i  i + 1){ second = strings.get(i + 1); } System.out.println("First [" + first + "] - Second [" + second + "]"); } 

结果是:

 First [item 1] - Second [item 2] First [item 2] - Second [item 3] First [item 3] - Second [item 4] First [item 4] - Second [null] 

我想实现:

 First [item 1] - Second [item 2] First [item 3] - Second [item 4] 

只需将i增加2:

 for(int i = 0; i < strings.size(); i += 2) { 

您需要为第二个值修改和增加i ,修改语句:

 second = strings.get(i + 1); 

 second = strings.get(++i); 

这也将增加i ,因为这似乎是期望的行为。

所以你的代码是:

 List strings = Arrays.asList("item 1", "item 2", "item 3", "item 4"); for(int i = 0; i < strings.size(); i++){ String first = strings.get(i); String second = null; if(strings.size() > i + 1){ second = strings.get(++i); //Change here } System.out.println("First [" + first + "] - Second [" + second + "]"); } 

我使用Java8 BiConsumer创建了以下方法:

 public static  void tupleIterator(Iterable iterable, BiConsumer consumer) { Iterator it = iterable.iterator(); if(!it.hasNext()) return; T first = it.next(); while(it.hasNext()) { T next = it.next(); consumer.accept(first, next); first = next; } } 

像这样用它:

 List myIterable = Arrays.asList("1", "2", "3"); tupleIterator(myIterable, (obj1, obj2) -> { System.out.println(obj1 + " " + obj2); }); 

这将输出:

 1 2 2 3 

如果在每次迭代中将i增加2,该怎么办? 应该做…否则考虑在实际循环内增加i

我们当然应该为一般情况提供解决方案;-)

 public static void main(String[] args) { List list = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }); for (Pair p : Pair.over(list)) { System.out.printf("%d, %d\n", p.first, p.second); } } static class Pair { T first; T second; public Pair(T first, T second) { this.first = first; this.second = second; } public static  Iterable> over(Collection collection) { return new PairWise(collection); } private static class PairWise implements Iterable>, Iterator> { final Iterator iterator; PairWise(Collection collection) { super(); this.iterator = collection.iterator(); } @Override public Iterator> iterator() { return this; } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public Pair next() { T first = null; T second = null; if (iterator.hasNext()) first = iterator.next(); else throw new NoSuchElementException(); if (iterator.hasNext()) second = iterator.next(); return new Pair(first, second); } @Override public void remove() { throw new UnsupportedOperationException(); } } } 
 List strings = Arrays.asList("item 1", "item 2", "item 3", "item 4"); int i = 0; for(; i < strings.size() - 1; i+=2){ String first = strings.get(i); String second = strings.get(i + 1); System.out.println("First [" + first + "] - Second [" + second + "]"); } //For odd sized lists if(i < strings.size()){ System.out.println("First [" + strings.get(i) + "]"); } 
 for(int i = 0; i < strings.size(); i++){ String first = strings.get(i++); String second = null; if(strings.size() > i){ second = strings.get(i); } System.out.println("First [" + first + "] - Second [" + second + "]"); } 
 List strings = Arrays.asList("item 1", "item 2", "item 3", "item 4"); for(int i = 0; i < strings.size(); i++){ if(i½2 = 0){ String first = strings.get(i); System.out.print("First [" + first + "] "); }else{ String second = strings.get(i + 1); System.out.println("- Second [" + second + "]"); } } 

为了提高性能,我建议您只计算一个列表的大小,而不是在每个新循环中创建一个新的字符串。

 List strings = Arrays.asList("item 1", "item 2", "item 3", "item 4"); int length = strings.size(); String first, second = null; for(int i = 0; i < length; i += 2){ ... } 

您可以避免使用迭代器进行索引; 这适用于任何Iterable ,而不仅仅是列表。 只需获取一个迭代器,并在每次循环迭代时增加两次:

 List strings = Arrays.asList("item 1", "item 2", "item 3", "item 4"); Iterator stringsIterator = strings.iterator(); while (stringsIterator.hasNext()) { String first = stringsIterator.next(); String second = stringsIterator.next(); System.out.println("First [" + first + "] - Second [" + second + "]"); } 

这假设一个偶数长度的列表,并且如果它是奇数长度则在最后一次传递时抛出NoSuchElementException 。 您可以通过各种方式处理此问题:

  • 用一个try ;
  • 有一个保护条款,预先检查长度是否均匀;
  • 在获得第二个元素之前检查。

检查第二个元素:

 List strings = Arrays.asList("item 1", "item 2", "item 3"); Iterator stringsIterator = strings.iterator(); while (stringsIterator.hasNext()) { String first = stringsIterator.next(); String second = stringIterator.hasNext() ? stringIterator.next() : null; System.out.println("First [" + first + "] - Second [" + second + "]"); } 

迭代器使一些人感到困惑,所以你也可以使用for-each循环和分支以及辅助触发器变​​量进行奇偶校验。 这更糟糕,因为它使循环的逻辑更简化迭代:而不是每次通过循环执行一次,按顺序并且没有分支,你必须经历两次并在心理上分支。 请注意,如果它是奇数长度,则会跳过最后一个元素; 如果想要处理这些情况,可以在之后添加对isFirst的检查。

 List strings = Arrays.asList("item 1", "item 2", "item 3", "item 4"); boolean isFirst = true; String first = null; String second = null; for (String string : strings) { if (isFirst) { first = string; isFirst = false; } else { second = string; isFirst = true; System.out.println("First [" + first + "] - Second [" + second + "]"); } } 

最后,请注意所有这些迭代器和辅助变量都有超出范围(它们仅用于循环本身,因此它们污染了本地环境):它们可以用块包装以限制范围,尽管通常会考虑生成的嵌套比超出范围更糟糕:

 List strings = Arrays.asList("item 1", "item 2", "item 3", "item 4"); { Iterator stringsIterator = strings.iterator(); while (stringsIterator.hasNext()) { String first = stringsIterator.next(); String second = stringsIterator.next(); System.out.println("First [" + first + "] - Second [" + second + "]"); } } 

现在在Java 8中,使用https://github.com/wapatesh/fig

你可以写:

 seq.forEachSlice(2, (values)->{ // [1,2] [3, 4] });