0

I want to remove all elements in ArrayList that are duplicates of the first element, but I want the firs element to remain in the ArrayList. I tried to do that with for loop, but it didn't remove all duplicates.

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

v1 is equal to the first element of the arraylist. I also tried with ListIterator, but it removed the first element

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

Can you please help me?

user2081119
  • 311
  • 3
  • 5
  • 12

5 Answers5

3

You need to read the first element separately, outside the while loop, and store it in some variable, with which you would compare the rest of the elements, to remove:

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() will return a value of type Integer. Using intValue() will give your primitive value out.

But since I'm doing the comparison with an int primitive itself, you won't need to call intValue() at all. Your Integer will automatically be unboxed to primitive int before comparison. So, replacing the if statement in while with the below one will also work:

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

As far as your first way is concerned, I would say, always use Iterator if you want to modify the List you are looping upon. This will prevent you from facing awkward ConcurrentModificationException.


See also:

Community
  • 1
  • 1
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • +1 - but you may want to add a bit about autoboxing and why you're using `iterator.next().intValue()` (and `int` first) given that in his example he's comparing reference values. – Brian Roach Feb 17 '13 at 19:40
1

Count down (not up):

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

You have to count down because as you remove elements, they the remaining ones shuffled down.

Also, you should change == to .equals() (as shown).

Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

You are doing the correct way by using Iterator and its method remove. But you should add a call to next() before the loop itself, in order to go over the first element and not remove it.

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

Contrary to what others have said, you don't have to use "equals" if v1 is an int, which seems to be the case.

Cyrille Ka
  • 15,328
  • 5
  • 38
  • 58
  • If the first code does not work, I suspect that `v1` is an `Integer`, not an `int`. But your code will work because it will get unboxed. – assylias Feb 17 '13 at 19:41
0
int v1 = arraylist.get(0);
for(int i = 0; i < arraylist.size(); i++) {
    if(arraylist.get(i) == v1){
       arraylist.remove(i);
       i--;
    }
}

If you don't want to use the Iterator approach: The other answers are correct in that you need to index from zero (if you want to remove the first one as well), but you also need to decrement your iteration variable (the i-- line) each time you remove an element from the list, because you're changing the list's length with remove().

kevinsa5
  • 3,301
  • 2
  • 25
  • 28
0

It's best to be careful about removing elements from an array (or an iterable list) whilst iterating over it.

Easiest approach, in my experience, is to create a new list. Can you consider doing that?

Looking at your code, firstly remember to use "equals" over "==" for comparison (since .equals means "meaningfully equivalent", which I think is what you need here). (edit: may not matter here due to autoboxing, but it's still a nice habit to have)

But even this won't work:

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

Since imagine you have an ArrayList of three integers, all the same. When i == 1, The element at index 1 is compared to the value at index 0, and removed. But then the element at index 2 becomes the element at index 1, the for-loop counter is incremented, thereby "missing" to remove the last entry in the list.

Can I recommend something like this?

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

Best of luck!

P.S. if you're feeling brave, you might be able to do a neat one-liner out of this: CollectionUtils.filter(Collection,Predicate)

CollectionUtils.filter(arraylist.subList(1, arraylist.size()), new Predicate() {
    @Override
    public boolean evaluate(Object o) {
        return !v1.equals(o);
    }
});
vikingsteve
  • 38,481
  • 23
  • 112
  • 156