3

I read a CSV file,which looks as shown below.

,Tmt 1,Tmt 2,Tmt 3
delta 1,-104,-100,-103
delta 2,-125,-103,-103
delta 3,-104,-100,failed

Later, I parsed the csv file and took in all of its elements to an ArrayList of Strings. Now the ArrayList looks like

[Tmt 1, Tmt 2, Tmt 3, delta 1, -104, -100, -103, delta 2, -125, -103, -103, delta 3, -104, -100, failed]

Now, I want to remove all the elements of the String ArrayList (shown above) which starts with an alphabet. I used the following code to do that. (al1 is the ArrayList I mentioned above and temp is the String I'm using to check the elements of al1)

for(int i=0;i<al1.size();i++)
  {   
    temp = al1.get(i);  
    if (temp.charAt(0)=='-'|| (Character.isDigit(temp.charAt(0))==false))
           {
               al1.remove(i);    
           }    
  }
System.out.print(al1); 

Now after the code runs and hoping to remove elements of al1 starting with an alphabet , I printed the ArrayList al1, and the result was as follows:

[Tmt 2, delts 1, -100, delta 2, -103, delta 3, -100]

(and this was not what I expected)

Please Help.. thanks in advance

3
  • 3
    Well what did you expect, and why? Have you stepped through this with a debugger, and worked out where things are going wrong? Have you determined whether the problem is with using the list, or with your string handling? One thing to bear in mind: if you remove an item from your list, everything else shuffles up... so the next item you want to check will have the same index as the one you just removed. You can fix that by adding i-- after the remove call. Or you could work your way from the end of the list towards the start. Commented Aug 15, 2015 at 7:41
  • Or you could just create another list containing only the elements you want to keep. Commented Aug 15, 2015 at 7:43
  • Jon Skeet, I was expecting that the resulting arraylist was devoid of elements starting with an alphabet. Commented Oct 30, 2015 at 17:56

3 Answers 3

2

The problem is you are using index to remove the element.

When you remove one element, your i will be off, after first removal you will not be removing the correct element.

Say your i is 5 and you have removed that element, in the next iteration when i is 6, when you do al1.get(i) you will actually get 7th element in the original list, not 6th because your 6th element index now is 5 but not 6. So you will not be able to access that element at all.

your for(int i=0;i<al1.size();i++) is also incorrect, because you are incrementing i and reducing the size of al1.

In worst case(when all the elements in the list starts with '-'), you will be able to traverse only half of the elements.

Safer way to do is using an Iterator.

Iterator<> it = al1.iterator();
while(it.hasNext()){
     temp = it.next();  
     if (temp.charAt(0)=='-'|| (Character.isDigit(temp.charAt(0))==false))
       {
           it.remove();    
       }  
}
Sign up to request clarification or add additional context in comments.

Comments

1

you can use built-in removeif method as:

al1.removeIf(new Predicate<String>() {

            @Override
            public boolean test(String t) {
                 if (t.charAt(0)=='-'|| (Character.isDigit(t.charAt(0))==false)){
                       return true;
                }
                return false;
            }
        });

1 Comment

removeIf() only exists since Java 8. So why not use a lambda instead of an anonymous class? al1.removeIf(t -> t.charAt(0)=='-'|| !Character.isDigit(t.charAt(0)));. Every time you have if (condition) return true; else return false;, you can write it return condition;
1

Here's what's happening.

The list is Tmt1, Tmt2, Tmt3, .... At the beginning, element 0 is Tmt1.

We consider this one for removal; it starts with a letter; so we remove it, and then move onto element 1 (the second one). But by that point we've removed one, so the list OS now Tmt2, Tmt3, ..., and we're considering the second one in the list, which is Tmt3! Tmt2 never gets looked at because it shifts backwards at the same time that your list shuffles forwards.

The nicest way to deal with this is the Java 8 streams API, which allows you to specify a filter over your list, and have it automatically remove all elements that don't meet the filter's requirements. It's concise and readable and much easier than a for loop.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.