首页 > 解决方案 > 连续迭代集合和数组的最佳方法

问题描述

这是一个非常微不足道的问题,与编码风格有关,我只是要求让我的编码风格更具可读性

假设我有一个像linkedList 和一个数组这样的集合,我需要同时迭代两者。
目前我知道的最好的方法是在列表上获取迭代器并在迭代器循环之外定义一个索引变量并同时增加索引变量以访问下一个元素 {list 和 array}。
请参考以下示例

LinkedList<Integer> list = new LinkedList<Integer>();
Integer[] arr = new Array[25];
// lets suppose both have 25 elements.

// My Iteration method will be 
int index =0;

for (Integer val : list) {
  System.out.println(val);
  System.out.println(arr[index++]);
}


那么这是唯一的方法还是有其他方法可以以更易读和更相关的方式执行此迭代,而我不必单独获取索引变量。
我知道数组可能有比集合更少或更多的元素,但我只是在谈论它们相等并且我们需要迭代它们两者的情况。

PS:任何人都可以编写计算机可以理解的代码,实际的挑战是编写人类可以轻松理解的代码。

标签: javacoding-style

解决方案


你所拥有的基本上没问题:它很简单,而且简单足以使代码可读。

index++我唯一要注意的是inside的副作用arr[index++]:如果你想在循环体中多次使用相同的值,你不能简单地复制+粘贴。

考虑将变量作为循环中的第一件事来存储“当前”数组元素(这本质上是增强的 for 循环对列表元素所做的)。

for (Integer val : list) {
  Integer fromArr = arr[index++];

  // ...
}

只是为了指出一个没有单独变量索引的替代方法,您可以使用ListIterator,它为您提供元素的索引。

// Assuming list and are have same number of elements.
for (ListIterator<Integer> it = list.listIterator();
    it.hasNext();) {
  // The ordering of these statements is important, because next() changes nextIndex().
  Integer fromArr = arr[it.nextIndex()];
  Integer val = it.next();

  // ...
}

ListIterator但是,它并不是一个特别广泛使用的类;它的使用本身可能令人困惑。


该方法的缺点之一ListIterator是您必须it正确使用:您不应该在循环内触摸它(在获取值之后),您必须以正确的顺序放置语句等。

另一种方法是创建一个类似于 Python 的库方法enumerate

static <T> Iterable<Map.Entry<Integer, T>> enumerate(Iterable<? extends T> iterable) {
  return () -> new Iterator<T>() {
    int index = 0;
    Iterator<? extends T> delegate = iterable.iterator();

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

    @Override public Map.Entry<Integer, T> next() {
      return new AbstractMap.SimpleEntry<>(index++, delegate.next());
    }
  };
}

这将返回一个可迭代的映射条目,其中键是索引,值是对应的值。

然后,您可以在增强的 for 循环中使用它:

for (Map.Entry<Integer, Integer> entry : enumerate(list)) {
  Integer fromList = entry.getValue();
  Integer fromArr = arr[entry.getKey()];
}

推荐阅读