Shi*_*isa 18 java foreach for-loop arraylist
我刚开始使用java中的列表.我想知道修改列表的每个元素的推荐方法是什么?
我已经能够用以下两种方法完成它,但它们看起来都相当不优雅.有没有更好的方法在java中完成这项工作?并且以下任何一种方法都推荐在另一种方法上,或者两者都处于同一水平?
//Modifying with foreach
for (String each : list)
{
list.set(list.indexOf(each), each+ " blah");
}
//Modifying with for
for (ListIterator<String> i = list.listIterator(); i.hasNext(); i.next())
{
i.next();
list.set(i.nextIndex()-1, i.previous() + " blah yadda");
}
Run Code Online (Sandbox Code Playgroud)
Two*_*The 23
第二个版本会更好.在内部它们最终是相同的,但第二个实际上允许您修改列表,而第一个实际上将抛出ConcurrentModificationException.
但是你以错误的方式使用迭代器.这是你如何正确地做到这一点:
for (final ListIterator<String> i = list.listIterator(); i.hasNext();) {
final String element = i.next();
i.set(element + "yaddayadda");
}
Run Code Online (Sandbox Code Playgroud)
迭代器是需要修改列表的那个,因为它是唯一一个知道如何正确执行该操作而不会对列表元素和顺序感到困惑的人.
编辑:因为我在所有评论和其他答案中都看到了这一点:
为什么不应该在循环中使用list.get,list.set和list.size
Java集合框架中有许多集合,每个集合都针对特定需求进行了优化.许多人使用ArrayList,它在内部使用数组.只要元素的数量随时间变化不大,并且具有get,set和size 在此特定类型的列表上的恒定时间操作的特殊好处,这是很好的.
然而,有其他列表类型,这是不正确的.例如,如果你有一个不断增长和/或收缩的列表,那么使用LinkedList要好得多,因为与ArrayList相比,add(element)是一个常量时间操作,但是add(index,element),get(索引)和删除(索引)不是!
要获取特定索引的位置,需要从第一个/最后一个遍历列表,直到找到特定元素.所以如果你在循环中这样做,这等于下面的伪代码:
for (int index = 0; index < list.size(); ++index) {
Element e = get( (for(int i = 0; i < size; ++i) { if (i == index) return element; else element = nextElement(); }) );
}
Run Code Online (Sandbox Code Playgroud)
迭代器是一种遍历列表的抽象方式,因此它可以确保遍历以每种列表的最佳方式完成.测试表明,使用迭代器和get(i)对于ArrayList,但在LinkedList上有很大的时间差(有利于迭代器)之间几乎没有时间差.
Jon*_*eet 10
编辑:如果您知道size(),get(index)并且set(index, value)对于您正在使用的操作(例如for ArrayList)都是常量操作,我个人会在这种情况下跳过迭代器:
for (int i = 0; i < list.size(); i++) {
list.set(i, list.get(i) + " blah");
}
Run Code Online (Sandbox Code Playgroud)
您的第一种方法效率低且可能不正确(因为indexOf可能返回错误的值 - 它将返回第一个匹配).你的第二种方法非常令人困惑 - 事实上,你打电话next()两次,previous一次让我很难理解.
当然,任何使用的方法List.set(index, value)对于没有恒定时间索引写访问的列表来说效率低下.正如Two所说,使用效果ListIterator.set(value)要好得多.两种使用a的方法ListIterator是更好的通用方法.
也就是说,在许多情况下,另一种替代方案是将您的设计更改为将一个列表投射到另一个列表 - 无论是视图还是实质性.如果您不更改列表,则无需担心.