-1

I have problem when i need to remove some items from list.

for (int i = 0; i < list.size() - 1; i++) {
    if (list.get(i).length() > 1 && list.get(i + 1).length() > 1) {
        list.remove(i+1);
        if(i != 0){
            i--;
        }
    }

I put 6 Strings which lenght are greater than 1 and I recieve in output 1st and 3rd. If I put at beggining string which legnth is 1 I recieve good output.

Juan Carlos Mendoza
  • 5,736
  • 7
  • 25
  • 50
Mateusz
  • 27
  • 3
  • 2
    I have no idea what you are asking and/or trying to tell us. – OH GOD SPIDERS Nov 02 '17 at 17:11
  • 5
    it will lead to a `ConcurrentModificationException` that means you can not modify a collection while iterating over it. – Mustapha Belmokhtar Nov 02 '17 at 17:12
  • @alfasin Yes I have that exception. – Mateusz Nov 02 '17 at 17:14
  • @mustabelMo and why so ? – Shubhendu Pramanik Nov 02 '17 at 17:18
  • Not sure why @mustabelMo 's comment was upvoted so many times... the OP would get a `ConcurrentModificationException` only if we would use an iterator to iterate the list while modifying it - which is not the case here. – Nir Alfasi Nov 02 '17 at 17:19
  • 1
    as shown [here](https://stackoverflow.com/questions/18448671/how-to-avoid-concurrentmodificationexception-while-removing-elements-from-arr) it was obvious that when foreach is used it leads to the cited exception above : `ConcurrentModificationException`, but here the iteration is performed using an index, sorry for the misleading comment. – Mustapha Belmokhtar Nov 02 '17 at 17:22

4 Answers4

1

It will be simpler to write and easier to understand the loop counter's value if you iterate from the end:

for (int i = list.size() - 1; i > 0; i--) {
    if (list.get(i).length() > 1 && list.get(i - 1).length() > 1) {
        list.remove(i);
    }
}
Shubhendu Pramanik
  • 2,711
  • 2
  • 13
  • 23
janos
  • 120,954
  • 29
  • 226
  • 236
  • Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 5, Size: 5 Its not working :( – Mateusz Nov 02 '17 at 17:26
  • 1
    @Mateusz I suspect you didn't copy paste. It will work if you copy paste it exactly as written here – janos Nov 02 '17 at 17:31
  • 1
    @Mateusz in particular, I suspect you overlooked that I changed the second condition to `list.get(i - 1)` from your original `list.get(i + 1)` – janos Nov 02 '17 at 17:33
0

Iterate from the end of the list to the beginning: since you're removing objects the indexes after the index you're removing are changing so if you're iterating from start to end you'll end up not iterating some of the items.

Example:

List has 3 items: [1, 2, 3], size = 3, i = 0, we're removing 1 (new list is: [2, 3]). Now size equals 2 and i is incremented: i = 1. now we've skipped 2!

Iterating in reverse can easily be implemented:

    for (int i = list.size() - 2; i >= 0; i--) {
        if (list.get(i).length() > 1 && list.get(i + 1).length() > 1) {
            list.remove(i + 1);
        }
    }

Update: If you know that you want to get rid of all the elements except one you can either build and new list with that one element and use it instead, or you can do something simpler such as:

list.removeIf(x -> x != 10000) // available from Java 8
Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
  • Okay but I have input like 10000 20000 30000 40000 50000 60000 and i need to keep only 10000 – Mateusz Nov 02 '17 at 17:16
  • @Mateusz sorry it's not clear to me what you're trying to do - can you update your question with further explanation? – Nir Alfasi Nov 02 '17 at 17:18
  • 2
    @Tom true, since `list.size()` is being evaluated every iteration (I wasn't aware of that - not sure that it's been like that in previous Java versions) the result will be that some of the items will not be traversed. Answer corrected. – Nir Alfasi Nov 02 '17 at 17:26
  • I don't think that this has been changed. Maybe you mean a different type of loop? Maybe something like `for(String s : getListOfStrings())` because `getListOfStrings()` will only evaluated once. – Tom Nov 02 '17 at 17:31
  • @Mateusz in that case you can do it even simpler: `list.removeIf(x -> x != 10000)` – Nir Alfasi Nov 02 '17 at 17:37
0

Not entirely sure what you are trying to do here, but I think you want to remove elements such that there are no two string with length > 1 in a row. While the general advice to loop the list in reverse order is sound, there might be reasons to loop the list in the right order.

Your idea with using i-- after removing an element was correct. But you have to do it in all cases, not only if you are not on the first element. Remove the if, then it should work.

for (int i = 0; i < list.size() - 1; i++) {
    if (list.get(i).length() > 1 && list.get(i + 1).length() > 1) {
        list.remove(i+1);
        i--;
    }
}

If i == 0, this will set i to -1, which may seem odd, but remember that i++ will set it back to 0 before the next iteration of the loop. So for 11, 22, 33, it will first compare 11 and 22, then remove 22, and continue comparing 11 and 33 (and remove 33 and so forth).

tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • 1
    OutOfBound Exception – Mateusz Nov 02 '17 at 17:33
  • @Mateusz Not when I tried it. For what input? Are you sure you haven't mixed up that fix with some other fixes? I do not see how this could possibly produce that error. Do you have any other operations _after_ the `if` block, maybe? – tobias_k Nov 02 '17 at 18:21
-2

The problem is you're going from 0 to list.size() - 2, but each time you remove an item from the list you're changing the index of the next items. So the next iteration will skip one item

The solution is to go from list.size() - 2 to 0, so that each time you remove an item the next iteration won't care. Your for would look something like this:

for (int i = list.size() - 2; i >= 0; i--) {
    if (list.get(i).length() > 1 && list.get(i + 1).length() > 1) {
        list.remove(i+1);
    }
}

Here you have the working result

Piyin
  • 1,823
  • 1
  • 16
  • 23
  • Woah, two downvotes without a reason. Weird thing is, I explained the cause of the error and gave a solution before the accepted answer (which was edited later). Do people think is the other way around? I have no idea. Should Stack Overflow make clearer to users when others edit their questions? Maybe. Hotel? Trivago – Piyin Nov 03 '17 at 04:23