2013-05-22 2 views
1

Я пытаюсь выполнить эту простую работу Java, но это не так, и я не могу понять, почему.Метод remove() из LinkedList не работает

Вот мой код:

public LinkedList<T> toSet() 
{ 
    LinkedList<T> retList; 
    retList = lista; 
    for(T elem1 : retList) 
     for(T elem2 :retList) 
     { 
      if(retList.indexOf(elem1) == retList.indexOf(elem2)) 
       continue; 
      else if(elem1.equals(elem2)) 
       retList.remove(elem1); 
     } 

    return retList; 
} 

Метод должен удалить элементы, которые появляются более чем один раз в списке. Я отлаживал его с помощью eclipse, и я обнаружил, что retList.remove(elem1) оставляет список без изменений!

Где моя ошибка?

+0

Если это сработало, оно выдаст исключение CommodificationException. Подумайте об использовании итераторов для ваших циклов. – ApproachingDarknessFish

+0

Я предлагаю вам использовать Set. Это гарантирует, что у вас нет дубликатов в первую очередь. –

+2

@ValekHalfHeart: Вы имеете в виду «ConcurrentModificationException»? – jlordo

ответ

5

Вы должны использовать .clone()

LinkedList<T> retList = (LinkedList<T>) lista.clone();

Кроме того, вам нужно использовать итераторы для удаления из LinkedList в то время как в цикле. См. Это SO answer.

1

Вы не можете удалить элементы из списка, итерации по нему с помощью цикла for-each. Вместо этого следует использовать итератор:

public LinkedList<T> toSet() 
{ 
    LinkedList<T> retList; 
    retList = lista; 
    Iterator<T> iter1 = retList.iterator(); 
    int index1 = 0; 
    while (iter1.hasNext()) { 
     T elem1 = iter1.next(); 
     Iterator<T> iter2 = retList.iterator(); 
     int index2 = 0; 
     while (iter2.hasNext()) 
     { 
      T elem2 = iter2.next(); 
      if(index1 != index2 && elem1.equals(elem2)) 
       iter2.remove(); 
      index2++; 
     } 
     index1++; 
    } 

    return retList; 
} 
+1

Я согласен на использование итераторов и удаляю только из 'remove' итератора. Однако, как бы то ни было, я думаю, что ваш 'iter2' должен быть создан * внутри * первым' while'. В противном случае на второй итерации внешнего цикла 'iter2' не будет' hasNext'. – afsantos

+0

Кроме того, не должен ли 'retList' быть новым списком и иметь' iter1' итератор из исходного списка? Не удалит ли элемент из 'iter2'' 'iter1', чтобы исключить исключение? – afsantos

+0

@afsantos Вы имеете право на 'iter2'. Благодаря! Что касается вашего второго комментария, я не уверен, будет ли это исключение или нет. Я не создал новый список, потому что OP не сделал. – Eran

5

Простым решением является использование набора. В вашем случае вы можете использовать.

public Set<T> toSet() { 
    return new LinkedHashSet<T>(lista); 
} 
1

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

Поскольку это упражнение, я не буду предоставлять полный код, но я опишу другой подход из других ответов.

  1. Создать новый, пустой, Map<T, Object>.
  2. Создайте объект, который будет служить значением, достаточно простого new Object().
  3. Создать новый, пустой, LinkedList<T>. Это список, который вы вернетесь.
  4. Создайте Iterator<T> из вашего списка. Это можно сделать с помощью lista.iterator().
  5. перебрать свой список, в то время как ваш итератор hasNext():
    1. Получить текущий элемент, используя ваш итератор next().
    2. Проверьте, есть ли ваша карта containsKey(), которая является элементом, полученным в 5.1.
      • Если это так, то элемент является дубликатом, и вы не добавите его в новый список. Просто пропустите.
      • Если нет, то элемент является новым, так что вы add() его в новый список, и put() его на карте, как ключ, указывающий на значение шаблонного, созданного в 2
    3. Repeat 5, т. Е. Цикл продолжается.
  6. Возврат нового списка, который не имеет дубликатов.
Смежные вопросы