在下面这段代码中,我发现总是删除第一个listnode并且打印第一个节点比保持列表完整并迭代所有节点更有效(就执行时间而言)。我想知道这是因为当我总是删除第一个节点时,我只需要将起始节点更新到下一个节点,然后只需获取第一个节点来打印该值。如果通过保持列表intanct迭代整个列表,则get操作每次遍历列表到指定的索引并获取值。 现在我的问题是: 1)我的理解是否正确? 2)两种方式都应该同时执行 3)还有其他推理吗?
public class Ddbrw {
public List<Integer> ListValidation()
{
List<Integer> lst = new LinkedList<>();
for(int i = 0; i < 20; i++ ){
lst.add(new Integer(1)); lst.add(new Integer(5));
lst.add(new Integer(9)); lst.add(new Integer(7));
lst.add(new Integer(5)); lst.add(new Integer(61));
lst.add(new Integer(8)); lst.add(new Integer(12));
}
return lst;
}
public static void main(String[] args)
{
Ddbrw obj = new Ddbrw();
Ddbrw obj2 = new Ddbrw();
List<Integer> lst = obj2.ListValidation();
int size = lst.size();
long startTime = System.currentTimeMillis();
for(int i = 0; i < size; i++) {
System.out.print(lst.get(i));
}
long endTime = System.currentTimeMillis();
System.out.println("*************");
System.out.println(endTime-startTime);
System.out.println("*************");
List<Integer> lst2 = obj.ListValidation();
long startTime1 = System.currentTimeMillis();
for(int k = 0; k < lst2.size(); ) {
System.out.print(lst2.get(k));
lst2.remove(k);
}
long endTime1 = System.currentTimeMillis();
System.out.println("*************");
System.out.println(endTime1-startTime1);
System.out.println("*************");
}
}
答案 0 :(得分:1)
您的初步推理是正确的,重点是LinkedList
并不意味着随机访问效率很高。因此,每次按索引访问元素时(例如lst.get(k)
),您都必须从列表的开头到达该元素。
但这并不意味着LinkedList
无法在您的情况下有效使用,只是您尝试将其用作ArrayList
。 List<T>
提供Iterator<T>
,在迭代列表时效率更高。
例如:
Iterator<Integer> it = lst.iterator();
while (it.hasNext())
System.out.println(it.next());
for (int i : lst)
System.out.println(i);
这将迭代列表而不必在每次迭代时到达k
个元素,因为它跟踪迭代器内的所有内容。
实际上,在某些情况下,这可能比ArrayList
更有效,因为每次删除元素时都不必记忆/移动连续的元素。
答案 1 :(得分:0)
您的观察结果与链接列表有关,只是因为您正在按索引遍历。 Java有一个RandomAccess
接口,用于标识可以在固定时间内编制索引的List
实现,例如由ArrayList
实现,但不是由LinkedList
实现。
如果您使用迭代器来遍历列表,那么您将获得大致相同的性能:
for (Integer i : lst) {
System.out.println(i);
}