Ваш метод является очень окольным способом достижения того, что вы хотите, и он довольно неэффективен.
Во-первых, вы перебираете строку и подсчитываете символы внутри кавычек,затем перебирая всю строку снова, считая все совпадающих символов и вычитая количество совпадающих символов в кавычках ... почему?Вместо этого просто посчитайте те, которые находятся вне кавычек, как вы хотите.
Во-вторых, используя s.toCharArray()
, вы по существу держите дубликаты данных и удваиваете объем памяти вашей строки;Вместо этого просто получите доступ к своим данным через charAt
.
В-третьих, использование стека для отслеживания того, находитесь ли вы внутри кавычек, не нужно;Вместо этого просто переверните логическое значение.
Вот мои заметки о вашем методе:
public static int countCurlyBraces(String s, char c) {
Deque<Character> stack = ...; // I'm assuming 'stack' is some kind of Deque
int count = 0;
// doubling memory usage of the string by copying the chars into another array with 's.toCharArray()'
// for each character in that string...
for (char cr : s.toCharArray()) {
// using a stack to keep track if you are inside quotes? just flip a boolean instead
if (cr == '"')
if (stack.isEmpty())
stack.push(cr);
else
stack.pop();
// if inside quotes and the character matches the target, then count it..
// I thought you wanted to count the characters outside the quotes?
if (stack.size() == 1 && cr == c)
count++;
}
// iterate through the whole string again and count ALL the characters
// then subtract the number inside the strings from the total to get the number outside strings
return StringUtil.countMatches(s, c) - count;
}
Вместо этого вы можете просто сделать что-то подобное, что гораздо эффективнее:
public static int countCharacterOutsideQuotes(CharSequence chars, char targetChar) {
int count = 0;
boolean isQuoted = false;
// using `charAt` avoids doubling memory usage of copying all the chars into another array
for (int i = 0; i < chars.length(); i++) {
char c = chars.charAt(i);
if (c == '"') {
// found a quote, flip from not quoted to quoted or vice versa.
isQuoted = !isQuoted;
} else if (c == targetChar && !isQuoted) {
// found the target character, if it's not inside quotes then count it
count++;
}
}
return count;
}
Если вы читаете данные из файла для начала, вы можете пропустить помещение их в строку и вместо этого просто прочитать их непосредственно с помощью Reader, что сэкономит память и также устранит замедлениеждать, пока файл будет прочитан, прежде чем вы сможете начать обработку.Используя Reader, вы можете сразу начать обработку и удерживать в памяти только один символ за раз.
public static int countCharacterOutsideQuotes(Reader reader, char targetChar) throws IOException {
Objects.requireNonNull(reader);
int count = 0;
boolean isQuoted = false;
// using `charAt` avoids doubling memory usage of copying all the chars into another array
for (int c = reader.read(); c != -1; c = reader.read()) {
if (c == '"') {
// found a quote, flip from not quoted to quoted or vice versa.
isQuoted = !isQuoted;
} else if (c == targetChar && !isQuoted) {
// found the target character, if it's not inside quotes then count it
count++;
}
}
return count;
}
public static void main(String[] args) {
// try (Reader reader = new InputStreamReader(new StringReader("your-test-string-goes-here"));) {
try (Reader reader = new InputStreamReader(new FileInputStream("/path/to/file.txt"));) {
System.out.println(countCharacterOutsideQuotes(reader, '{'));
} catch (IOException e) {
e.printStackTrace();
}
}