[英]Java why does no third syntax for for (each) loops exist?
I know that currently there are two approaches to loop over an List
. 我知道,目前有两种方法可以遍历
List
。 But let's complicate it a bit more, consider: 但让我们复杂一点,请考虑:
List<E> list
. List<E> list
。 int y
on every iteration. int y
。 process(E elem, int y)
that processes an item. process(E elem, int y)
的功能process(E elem, int y)
。 Option 1: 选项1:
for (int i = 0, y = 0; i < list.size(); i++, y++) {
process(list.get(i), y);
}
which actually just is 其实就是
for (int i = 0; i < list.size(); i++) {
process(list.get(i), i);
}
Option 2: 选项2:
int y = 0;
for (E elem : list) {
process(elem, y);
y++;
}
which can be rewritten to 可以重写为
int y = 0;
for (E elem : list) {
process(elem, y++);
}
However why does the following not exist? 但是为什么不存在以下内容? What are the objections to it not existing?
对它不存在哪些异议?
Option 3: 选项3:
for (int y = 0; E elem : list; y++) {
process(elem, y);
}
Two arguments to have this construct: 具有此构造的两个参数:
foreach
syntaxes are distinguishable foreach
语法都是可区分的 Iterable<E>
, but have no for
counterpart. Iterable<E>
,但没有for
对应对象。 This happens when an Iterable<E>
has no order associated with it for example. Iterable<E>
没有与之关联的顺序时,就会发生这种情况。 This is close to the proposed variant 3: 这接近于建议的变体3:
int y = 0;
for (Iterator<E> it=list.iterator(); it.hasNext(); y++) {
process(it.next(), y);
}
or 要么
Iterator<E> it=list.iterator();
for (int y = 0; it.hasNext(); y++) {
process(it.next(), y);
}
or 要么
Iterator it;int y;
for (y = 0, it=list.iterator(); it.hasNext(); y++) {
process(it.next(), y);
}
Because it's excessive? 因为过量吗? In this case
y
doesn't bear any sense and code can be easily rewritten as you've shown. 在这种情况下,
y
毫无意义,并且您可以如所示轻松地重写代码。
If you want such a nonstandard behaviour, maybe try to look at Scala language, for example. 如果您想要这种非标准的行为,例如,可以尝试查看Scala语言。 You'll be able to create truly monstrous control structures there.
您将能够在那里创建真正可怕的控制结构。
This : 这个 :
for (int y = 0; E elem : list; y++) {
process(elem, y);
}
can very well be written as this : 可以这样写:
E elem;
for (int y = 0 ; y < list.size(); y++, elem = list.get(y)) {
process(elem, y);
}
Though the scope of the variable elem
differs in this case . 尽管在这种情况下变量
elem
的范围有所不同。 Hence I don't think there is an explicit need for the 3rd option , again , opinions may vary . 因此,我认为没有明显的选择第三选择的可能,意见可能会有所不同。
In a language like Python, this could be solved by zipping with an integer sequence: 在像Python这样的语言中,这可以通过以整数序列压缩来解决:
>>> a = ['a','b','c','d']
>>> for val,i in zip(a, range(len(a))):
... print val, i
...
a 0
b 1
c 2
d 3
Obviously Java doesn't have syntactic support for something like this, but I do think there can be good reasons for avoiding calling list.get(i)
on each iteration, not least that fetching a specific value might be much slower than iterating to the next value (say, with a linked list). 显然,Java对此不提供语法支持,但是我确实认为有充分的理由避免在每次迭代中都调用
list.get(i)
,不仅如此,获取特定值可能比迭代到它慢得多。下一个值(例如,带有链表)。
I'm not a fan of departing from convention when using loop syntax, so I'm not so keen on putting different variables in the test and increment portions of a normal for-loop (Alexei Kaigorodov's solution looks nice, but potentially confusing for people who aren't familiar with it). 我不喜欢在使用循环语法时偏离约定,因此我不太热衷于在常规for循环的测试和增量部分中放置不同的变量(Alexei Kaigorodov的解决方案看起来不错,但可能会使人感到困惑谁不熟悉)。 My usuallly-preferred solution is to maintain the count separately while using a for-each loop, which is the OP's Option 2.
我通常首选的解决方案是在使用for-each循环(这是OP的选项2)时分别维护计数。
Alternatively, you could use my CountingIterable<> class, which provides the count as well as the value. 或者,您可以使用我的CountingIterable <>类,该类提供计数和值。 Whether this is a good idea in production code is still up for debate, but the question inspired me to write it and stick it on Github .
在生产代码中这是否是一个好主意尚有待商debate,但这个问题激发了我编写并将其粘贴在Github上的疑问。
It's used like this: 它的用法如下:
for (Counted<E> v : counting(iterable)) {
process(v.getValue(), v.getCount());
}
(Where, in the code this was taken from, counting
is statically imported from the Counting
class) (在此代码中,
counting
是从Counting
类静态导入的)
I believe this is an opinion based question. 我相信这是一个基于意见的问题。 Only the language designers could answer that.
只有语言设计师才能回答这个问题。
You could somewhat improve the Iterator
syntax with a utility class, if you are willing to accept the creation of a new object that wraps Iterator
to make the index available. 如果您愿意接受创建一个包装了
Iterator
的新对象以使索引可用的方法,则可以通过实用工具类对Iterator
语法进行某种程度的改进。 See an example below: 请参阅以下示例:
public static void main(String[] args) {
List<String> list = Arrays.asList( new String[] {"item1", "item2", "item3"} );
for (IndexIterator<String> it = IndexIterator.of(list.iterator()); it.hasNext();) {
System.out.println( it.next() + " : " + it.index() );
}
// Prints:
// item1 : 0
// item2 : 1
// item3 : 2
}
The IndexIterator
utility class is as follows: IndexIterator
实用程序类如下:
public static class IndexIterator<T> implements Iterator<T> {
private int index = -1;
private Iterator<T> iterator;
public IndexIterator(Iterator<T> it) {
this.iterator = it;
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public T next() {
index++;
return iterator.next();
}
@Override
public void remove() {
iterator.remove();
}
public int index() {
return this.index;
}
public static <T> IndexIterator<T> of(Iterator<T> it) {
return new IndexIterator<T>(it);
}
}
Isn't 是不是
nextIndex()
what you are looking for instead of y? 您在寻找什么而不是y? Ps using ListIterator
使用ListIterator的PS
Edited: this is what I meant in code: 编辑:这就是我在代码中的意思:
Iterator<E> it = list.iterator();
while (it.hasNext()){
process(it.next(), it.previousIndex());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.