1

So, I have an ArrayList called totalListOfWords. It contains a mixed of words from which has both lower and upper case letters in it. I want to remove all the words that contain upper case letter in them. Below is what I have.

I have a helper method called containsUpperCaseLetter. It basically checks whether a string contain an upper case letter in it.

Then I loop through my totalListOfWords using for loop and check each word in the list whether it contains an upper case letter. If so, I try to remove it. But it only remove some words. May be I am choosing the wrong type? Help please.

public class TextProcessor() {
   ArrayList<String> totalListOfWords = new ArrayList<String>();
   
   totalListOfWords.add("The");
   totalListOfWords.add("Project");
   totalListOfWords.add("Gutenberg");
   totalListOfWords.add("eBook");
   totalListOfWords.add("of");
   totalListOfWords.add("Pride");
   totalListOfWords.add("and");
   totalListOfWords.add("Prejudice");
   totalListOfWords.add("by");
   totalListOfWords.add("Jane");
   totalListOfWords.add("Austen");

   public void processText() {
      for (int i = 0; i < totalListOfWords.size(); i++) {
         if(containsUpperCaseLetter(totalListOfWords.get(i))){
            totalListOfWords.remove(i);
         }
      }
      System.out.println(totalListOfWords);  
   }   

   public boolean containsUpperCaseLetter(String s){
      for(int i = 0; i < s.length(); i++){
          if(Character.isUpperCase(s.charAt(i))){
              return true;
          }
      }
      return false;
   }

   public static void main(String[] args) {
      TextProcessor t1 = new TextProcessor();
      t1.processTextAtURL(url1);
   }
}
james
  • 13
  • 4
  • 2
    Step through your code with the debugger and look at which words actually get checked. Think about the effect of removing words on the indices of the other words. – tgdavies Mar 23 '22 at 04:32
  • 1
    Hi, I think this will help: https://stackoverflow.com/a/36669154. It's for a different language, but explains the problem. – tresf Mar 23 '22 at 04:32
  • If you remove an item from the arrayList (The same one you are currently iterating), then the very next item replaces the current item, and will be missed entirely in your loop. – sorifiend Mar 23 '22 at 04:33
  • Be weary of blindly checking uppercase without setting locale so that your app doesn't break in some countries. For example, in Turkey, a lowercase `I` may change to `ı` (notice the missing dot). – tresf Mar 23 '22 at 04:39
  • You don't need the **containsUpperCaseLetter()** method. You can do all this with one line: `totalListOfWords.removeIf(strg -> !strg.equals(strg.toLowerCase()));`. Now you just need to display what remains within the ArrayList. – DevilsHnd - 退職した Mar 23 '22 at 05:26
  • Thanks for all the help. I really do appreciate it. – james Mar 23 '22 at 06:14

1 Answers1

4

When you remove the element at index i, the next element is now at i instead of i+1. You would have to decrement i so it checks the same index again:

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

Or you can use an iterator instead:

for (Iterator<String> iter = totalListOfWords.iterator(); iter.hasNext();) {
    if (containsUpperCaseLetter(iter.next())) {
        iter.remove();
    }
}

Or you can skip the whole loop altogether:

totalListOfWords.removeIf(word -> containsUpperCaseLetter(word));
shmosel
  • 49,289
  • 6
  • 73
  • 138