字符串索引超出范围:22 异常 Java

String index out of range: 22 exception Java

我一直收到 String index out of bound: 22 异常。谁能告诉我我做错了什么?这是代码:

class Troll {
    private static final char[] VOWELS = {'a', 'A', 'e', 'E', 'i', 'I', 'o', 'O', 'u', 'U'};

    public static String disemvowel(String str) {
        int lengthStr = str.length();
        int lengthVOWELS = VOWELS.length;

        for (int i = 0; i < lengthStr; ++i)
            for (char vowel : VOWELS)
                if (str.charAt(i) == vowel)
                    str = removeChar(str, i);

        return str;
    }

    private static String removeChar(String str, int index) {
        return str.substring(0, index) + str.substring(index + 1);
    }
}

我想在这里做的是编写一个函数,它接受一个字符串和 return 一个删除了所有元音的新字符串。

When you make a string shorter, you reduce its length. But you're storing the initial string length, and using it as the loop bound.

Change i < lengthStr to i < str.length().


That fixes part of the problem, which is the IndexOfOfBoundsException. The other problem is that, having removed a character, you need to make sure that you check the next character fully too.

Consider the string aa:

  • You'd find the a at position 0, and remove it.
  • The next a is now at position 0; you'd skip over checking if it's a vowel
  • You'd move onto check position 1 next.

It would work if you string contained vowels in order of checking (e.g. aeiou), but not in general.

Having removed a character, you need to stop looping over other vowels, and then decrement i, in order to make sure that you check the character immediately following the one you removed:

    for (int i = 0; i < lengthStr; ++i) {
        for (char vowel : VOWELS) {
            if (str.charAt(i) == vowel) {
                str = removeChar(str, i);
                // Decrement i, so it gets incremented back to the
                // same value on the next iteration of the outer loop.
                --i;
                break;  // Break out of vowels loop.
            }
        }
    }

However, this is a very inefficient way to approach the problem: every time you remove one vowel, you rebuild the rest of the string, including all the vowels you're going to subsequently remove.

If you want to do this without regex, the best way is to create a StringBuilder, and only add the non-vowels to it:

StringBuilder sb = new StringBuilder(lengthStr);
for (int i = 0; i < lengthStr; ++i) {
  char c = str.charAt(i);
  if (!isVowel(c) {
    sb.append(c);
  }
}
str = sb.toString();

where isVowel is a method which returns whether the given char is a vowel, e.g.

boolean isVowel(char c) {
  return "aAeEiIoOuU".indexOf(c) >= 0;
}

试试这个。

private static final String VOWELS = "aAeEiIoOuU";

public static String disemvowel(String str) {
    return Stream.of(str.split(""))
        .filter(c -> !VOWELS.contains(c))
        .collect(Collectors.joining());
}
    public static String disemvowel(String str) {
        return str.replaceAll("[aeiou]", "");
    }

正是您所需要的。如果您还想要大写字母,请使用 "[aeiouAEIOU]" 然后。这将使生成的字符串仅通过原始字符串一次。