Сравнение двух LinkedList с ListIterator против for loop и get (индекс int)

У меня есть два объекта LinkedList, которые всегда имеют одинаковый размер. Я хочу сравнить их, чтобы увидеть, если они идентичны по содержанию. Каковы общие последствия для производительности и стиля создания Листератора для каждого списка и использования цикла while hasNext по сравнению с использованием счетчика (int i) и итерации от 0 до linkedlist.размер () с помощью linkedlist.получить (i), чтобы получить и сравнить значения? Есть ли лучший способ, который я упускаю из виду?

единственное, что я могу думать, что метод ListIterator может быть лучше в том, что я мог бы легче поменять в другом сопоставимом списке позже (не то, что я планирую на него). Я не знаю, как они выглядят под капотом, поэтому я не уверен,как бы я сравнил их с производительностью.

3 ответов


как выяснилось AbstractList.equals() (где LinkedList uses) сделает это автоматически, поэтому используйте это. Код:

public boolean equals(Object o) {
  if (o == this)
    return true;
  if (!(o instanceof List))
    return false;

  ListIterator<E> e1 = listIterator();
  ListIterator e2 = ((List) o).listIterator();
  while (e1.hasNext() && e2.hasNext()) {
    E o1 = e1.next();
    Object o2 = e2.next();
    if (!(o1 == null ? o2 == null : o1.equals(o2)))
      return false;
  }
  return !(e1.hasNext() || e2.hasNext());
}

так что не изобретайте колесо.

последнее примечание: не используйте get(index) для перебора LinkedList. Это o (n) доступ(O (1) для ArrayList) так LinkedList обход с помощью get(index) будет O (n2).


случайный доступ в LinkedList имеет ужасную производительность (она должна начинаться с одного конца и вызывать next или подобное неоднократно), поэтому ListIterator будет быстрее.


get(n) для связанных списков не является постоянной операцией для классов, которые расширяются AbstractSequentialList, это O(n). От AbstractSequentialList#get (int index):

эта реализация сначала получает итератор списка, указывающий на индексированный элемент (с listIterator(index)). Затем он получает элемент, используя ListIterator.next и возвращает его.

как правило, вы не хотите делать случайный доступ к коллекциям, которые не реализуют интерфейс маркера java.util.RandomAccess.

как правило, реализация списка должна реализовать этот интерфейс, если для типичных экземпляров класса этот цикл:

 for (int i=0, n=list.size(); i < n; i++)
     list.get(i);

работает быстрее, чем этот цикл:

 for (Iterator i=list.iterator(); i.hasNext(); )
     i.next();

начиная с Java SE 6, реализующими классами являются ArrayList, AttributeList, CopyOnWriteArrayList, RoleList, RoleUnresolvedList, Stack, Vector.