Подсчет определенного символа в строке (Java) - PullRequest
2 голосов
/ 10 марта 2010

String a = "(Дааааа) Я наконец-то добрался до (вверху)";

Учитывая выше String, всего 4 из '(' и ')'.

Моя идея считать это с помощью метода String.charAt.Тем не менее, этот метод довольно медленный, поскольку мне приходится выполнять этот подсчет для каждой строки как минимум 10000 раз из-за характера моего проекта.

У кого-нибудь есть идеи или предложения лучше, чем использование метода .chartAt ?????

Извините за то, что ранее я не объяснил четко, что я имел в виду для 10000 раз, для того, чтобы проанализировать 10000 предложений, что является приведенной выше строкой a как одно предложение.

Ответы [ 6 ]

6 голосов
/ 10 марта 2010

StringUtils.countMatches(wholeString, searchedString) (из commons-lang )

searchedString может быть одним символом - "("

Он (как отмечено в комментариях) вызывает charAt(..) несколько раз. Однако в чем сложность? Ну, его O(n) - charAt(..) имеет сложность O(1), поэтому я не понимаю, почему вы находите его медленным.

6 голосов
/ 10 марта 2010

Звучит как домашнее задание, поэтому я постараюсь держать его в «толчке в правильном направлении».

Что если вы удалили все символы, а НЕ символ, который вы ищете, и посмотрите на длину этой строки?

Существует метод String, который поможет вам в этом.

2 голосов
/ 10 марта 2010

Вы можете использовать toCharArray() один раз и повторить это. Это может быть быстрее.

Зачем вам нужно делать это 10000 раз на строку? Почему вы просто не помните результат первого раза? Это сэкономит гораздо больше, чем просто ускорит счет.

1 голос
/ 11 марта 2010

Вы можете сделать это с помощью регулярных выражений:

Pattern pattern = Pattern.compile("[\\(\\)]"); //Pattern says either '(' or ')'
Matcher matcher = pattern.matcher("(Yeahhhh) I have finally made it to the (top)");
int count = 0;
while (matcher.find()) { //call find until nothing is found anymore
  count++;
}
System.out.println("count "+count);

Pro заключается в том, что Patterns очень гибкие. Вы также можете выполнить поиск объединенных слов: "\\(\\w+\\)" (A '(', за которым следует один или несколько символов слова, а затем ')')

Мошенничество в том, что это может быть похоже на разбитие мухи на колесе для очень простых случаев

См. Javadoc Pattern для получения дополнительной информации о регулярных выражениях

1 голос
/ 10 марта 2010

Этого можно добиться следующим способом.

Этот метод возвращает карту с ключом в качестве символа и значением в качестве его вхождения во входной строке.

Map countMap = new HashMap ();

public void updateCountMap(String inStr, Map<Character, Integer> countMap)
    {
        char[] chars =  inStr.toCharArray();
        for(int i=0;i<chars.length;i++)
        {
            if(!countMap.containsKey(chars[i]))
            {
                 countMap.put(chars[i], 1);
            }
            countMap.put(chars[i] ,countMap.get(chars[i])+1);
        }
        return countMap;        
    }

То, что мы можем сделать, это прочитать файл построчно и вызвать вышеупомянутый метод для каждой строки. Каждый раз, когда карта будет продолжать добавлять значения (количество вхождений) для символов. Таким образом, размер массива символов никогда не будет слишком длинным, и мы достигнем того, что нам нужно.

Преимущество: Одна итерация по символам входной строки. Размер символьного массива никогда не увеличивается до предела. Карта результатов содержит вхождения для каждого персонажа.

Приветствия

0 голосов
/ 30 марта 2014

Я проверил следующие методы для строк 10M для подсчета символа ",".

// split a string by ","
public static int nof1(String s)
{
  int n = 0;
  if (s.indexOf(',') > -1)
    n = s.split(",").length - 1;
  return n;
} // end method nof1

// count "," using char[]
public static int nof2(String s)
{
  char[] C = s.toCharArray();
  int n = 0;
  for (char c : C)
  {
    if (c == ',')
      n++;
  } // end for c
  return n;
} // end method nof2

// replace "," and calculate difference in length
public static int nof3(String s)
{
  String s2 = s.replaceAll(",", "");
  return s.length() - s2.length();
} // end method nof3

// count "," using charAt
public static int nof4(String s)
{
  int n = 0;
  for(int i = 0; i < s.length(); i++)
  {
    if (',' == s.charAt(i) )
      n++;
  } // end for i
  return n;
} // end method nof4

// count "," using Pattern
public static int nof5(String s)
{
  // Pattern pattern = Pattern.compile(","); // compiled outside the method
  Matcher matcher = pattern.matcher(s);
  int n = 0;
  while (matcher.find() )
  {
    n++;
  }
  return n;
} // end method nof5

Результаты:

nof1: 4538 ms
nof2:  474 ms
nof3: 4357 ms
nof4:  357 ms
nof5: 1780 ms

Итак, charAt - самый быстрый. Кстати, grep -o ',' | wc -l заняло 7402 мс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...