2

I have a String hashset (called "names") and I want to remove from it all the Strings that contains at least one char that isn't a capital letter. I wrote this code and it doesn't work:

Iterator<String> iterator=names.iterator();
while(iterator.hasNext()) {
    for (int i=0; i<iterator.next().length(); i++) {
        if (iterator.next().charAt(i) < 'A' || iterator.next().charAt(i) > 'Z') {
            names.remove(iterator.next());
        }
    }
}
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140

2 Answers2

5

Another solution if you are using Java-8 by using removeIf and regex [A-Z]+ like so :

Set<String> names = //.. some inputs
names.removeIf(str -> !str.matches("[A-Z]+")); // remove if not matches [A-Z]+

Note in this solution you don't need to convert your list to an iterator at all, and not need to check your characters by a loop, just you can match by regex.

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
4

There are three issues with your code:

  1. You should call iterator.next() once in each iteration of the while loop (since each call to iterator.next() returns a different element).

  2. You should use the Iterator's remove method to delete the current element (that's the only valid way to make a structural change in a Collection while iterating over it).

  3. You should break out of the loop when you remove the current element, in order to avoid trying to remove the same element multiple times.

    Iterator<String> iterator = names.iterator();
    while (iterator.hasNext()) {
        String str = iterator.next();
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) < 'A' || str.charAt(i) > 'Z') {
                iterator.remove();
                break;
            }
        }
    }
    
Eran
  • 387,369
  • 54
  • 702
  • 768
  • You could have a check `!Character.isUpperCase(str.charAt(i))` instead of `str.charAt(i) < 'A' || str.charAt(i) > 'Z'`. – Anatolii Nov 24 '19 at 08:51
  • @Anatolii that's true if all the characters in the input strings belong to the English alphabet. Otherwise, checking `Character.isUpperCase(str.charAt(i))` may return true also for upper case letters of other alphabets. – Eran Nov 24 '19 at 08:55
  • Interesting. Could you please provide a source to this observation? – Anatolii Nov 24 '19 at 09:07
  • @Anatolii read the Javadoc of `isUpperCase()`. You'll see that it returns true not only for the characters between 'A' and 'Z', but also for characters such as '\u00C0' '\u00C1' '\u00C2' '\u00C3' '\u00C4' '\u00C5' etc... – Eran Nov 24 '19 at 10:40