2013-02-17 3 views
0

Я хочу удалить все элементы в ArrayList, которые являются дубликатами первого элемента, но я хочу, чтобы элемент firs оставался в ArrayList. Я попытался сделать это с помощью цикла, но не удалил все дубликаты.Удалите все вхождения первого элемента в ArrayList

for(int i = 1; i < arraylist.size(); i++) { 
    if(arraylist.get(i) == v1) 
     arraylist.remove(i); 
} 

v1 равно первому элементу архаиста. Я также попытался с ListIterator, но он удаляется первый элемент

ListIterator<Integer> iterator = arraylist.listIterator(); 
while(iterator.hasNext()) { 
    if(iterator.next().intValue() == v1) 
    iterator.remove(); 
} 

Можете ли вы мне помочь?

+1

Элемент нумерация начинается с 0 (и так ИНТ я должен начать там тоже). –

+3

Это не нужно, если он выполняет итерацию, чтобы удалить все элементы, которые являются дубликатами первого, поскольку первый никогда не является фактическим дубликатом. Я полагаю, что его переменная v1 установлена ​​в arraylist.get (0). –

+0

@JeffLaJoie: Очень хороший момент, не подумал об этом. –

ответ

1

Граф вниз (не вверх):

Object v1 = arraylist.get(0); 
for (int i = arraylist.size() - 1; i > 1; i--) { 
    if (arraylist.get(i).equals(v1)) 
     arraylist.remove(i); 
} 

Вы должны отсчитывать, потому что, как вы удалите элементы, они остальные перемешиваются вниз.

Кроме того, вы должны изменить == на .equals() (как показано).

1

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

ListIterator<Integer> iterator = arraylist.listIterator(); 
iterator.next(); // pass the first element. 
while(iterator.hasNext()) { 
    if(iterator.next().intValue() == v1) 
    iterator.remove(); 
} 

Вопреки тому, что говорят другие, вы не должны использовать «равно», если v1 является int, который, кажется, так.

+0

Если первый код не работает, я подозреваю, что 'v1' является' Integer', а не 'int'. Но ваш код будет работать, потому что он будет распакован. – assylias

3

Вы должны прочитать первый элемент отдельно, вне while loop, и хранить его в какой-либо переменной, с помощью которого вы бы сравнить остальные элементы, чтобы удалить:

ListIterator<Integer> iterator = arraylist.listIterator(); 
int first = 0; 
// Check if there is a first element 
if (iterator.hasNext()) { 
    first = iterator.next(); 

    // Iterate over the rest of the elements 
    while(iterator.hasNext()) { 
     // If this value is equal to `first`, remove it 
     if(iterator.next().intValue() == first) { 
      iterator.remove(); 
     } 
    } 
} 
System.out.println(arrayList); 

iterator.next() возвратит значение типа Integer. Используя intValue(), вы получите примитив.

Но поскольку я делаю сравнение с самим примитивом int, вам не нужно будет звонить intValue() вообще. Ваш Integer будет автоматически unboxed до примитива int перед сравнением. Таким образом, заменив if заявление, в то время как с приведенной ниже будет также работать:

if(iterator.next() == first) { 
    iterator.remove(); 
} 

Насколько ваш первый путь, то я бы сказал, всегда использовать Iterator, если вы хотите изменить List вас зацикливаются. Это не позволит вам столкнуться с неудобством ConcurrentModificationException.


Смотрите также:

+0

+1 - но вы можете добавить немного об автобоксинге и о том, почему вы используете 'iterator.next(). IntValue()' (и 'int'), так как в его примере он сравнивает эталонные значения. –

+1

@BrianRoach. Конечно. Добавлено некоторое объяснение :) –

0
int v1 = arraylist.get(0); 
for(int i = 0; i < arraylist.size(); i++) { 
    if(arraylist.get(i) == v1){ 
     arraylist.remove(i); 
     i--; 
    } 
} 

Если вы не хотите использовать подход итератора: Другие ответы правильны в том, что вам нужно индекс с нуля (если вы хотите также удалить первый), но вам также необходимо уменьшить вашу итерационную переменную (i--) каждый раз, когда вы удаляете элемент из списка, потому что вы меняете длину списка с помощью remove().

0

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

Самый простой подход, по моему опыту, состоит в том, чтобы создать новый список. Вы можете это сделать?

Если вы посмотрите на свой код, во-первых, помните, что для сравнения используйте «equals» над «==» (поскольку .equals означает «значимо эквивалентный», который, я думаю, вам нужен здесь). (Редактирование: не имеет значения, здесь из-за Autoboxing, но это все-таки хорошая привычка есть)

Но даже это не будет работать:

for (int i = 1; i < arraylist.size(); i++) { 
    if (arraylist.get(i).equals(v1)) 
     arraylist.remove(i); 
} 

Так представьте, у вас есть ArrayList из трех целых чисел, все тоже самое. Когда i == 1, элемент в индексе 1 сравнивается со значением в индексе 0 и удаляется. Но тогда элемент в индексе 2 становится элементом в индексе 1, счетчик для цикла увеличивается, поэтому «отсутствует» для удаления последней записи в списке.

Могу ли я рекомендовать что-то подобное?

List<Integer> newlist = new ArrayList<Integer>(); 
newlist.add(v1); 
for (Integer integer : arraylist) { 
    if (!integer.equals(v1)) 
     newlist.add(integer); 
} 

Удачи!

P.S. если вы чувствуете себя храбрым, вы могли бы быть в состоянии сделать аккуратный Однострочник из этого: CollectionUtils.filter(Collection,Predicate)

CollectionUtils.filter(arraylist.subList(1, arraylist.size()), new Predicate() { 
    @Override 
    public boolean evaluate(Object o) { 
     return !v1.equals(o); 
    } 
}); 
Смежные вопросы