[java] 문자열에서 문자 발생 횟수를 어떻게 계산합니까?

나는 문자열이

a.b.c.d

‘.’의 발생 횟수를 계산하고 싶습니다. 관용적 방식으로, 바람직하게는 하나의 라이너.

(이전에는 모든 사람들이 루프를 사용하지 않고 응답하려고하는 이유가 궁금한 경우를 대비하여이 제약 조건을 “루프없이”로 표현했습니다.)



답변

이것에 대한 나의 ‘아이디 오 메틱 원 라이너’는 다음과 같습니다.

int count = StringUtils.countMatches("a.b.c.d", ".");

이미 commons lang 에있을 때 직접 작성해야하는 이유는 무엇 입니까?

이를위한 Spring Framework의 oneliner는 다음과 같습니다.

int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");


답변

이건 어때요. 아래에 정규 표현식을 사용하지 않으므로 다른 솔루션보다 빠르며 루프를 사용하지 않습니다.

int count = line.length() - line.replace(".", "").length();


답변

다른 답변과 하나의 라이너를 사용 하여이 작업을 수행하는 모든 방법을 요약하면 다음과 같습니다.

   String testString = "a.b.c.d";

1) Apache Commons 사용

int apache = StringUtils.countMatches(testString, ".");
System.out.println("apache = " + apache);

2) 스프링 프레임 워크 사용

int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, ".");
System.out.println("spring = " + spring);

3) 바꾸기 사용

int replace = testString.length() - testString.replace(".", "").length();
System.out.println("replace = " + replace);

4) replaceAll 사용 (사례 1)

int replaceAll = testString.replaceAll("[^.]", "").length();
System.out.println("replaceAll = " + replaceAll);

5) replaceAll 사용 (사례 2)

int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length();
System.out.println("replaceAll (second case) = " + replaceAllCase2);

6) 분할 사용

int split = testString.split("\\.",-1).length-1;
System.out.println("split = " + split);

7) Java8 사용 (사례 1)

long java8 = testString.chars().filter(ch -> ch =='.').count();
System.out.println("java8 = " + java8);

8) Java8 (case 2 )을 사용하면 case 1보다 유니 코드에 더 좋습니다.

long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count();
System.out.println("java8 (second case) = " + java8Case2);

9) StringTokenizer 사용

int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1;
System.out.println("stringTokenizer = " + stringTokenizer);

코멘트에서 : StringTokenizer, abcd의 경우 작동하지만 a … bc … d 또는 … abcd 또는 a …. b …… c ….. d에주의하십시오. … 등이 작동하지 않습니다. 그냥 계산됩니다. 한 번만 문자 사이

github에 대한 추가 정보

성능 테스트 ( JMH 사용 , 모드 = AverageTime, 0.010다음보다 우수 0.351) :

Benchmark              Mode  Cnt  Score    Error  Units
1. countMatches        avgt    5  0.010 ±  0.001  us/op
2. countOccurrencesOf  avgt    5  0.010 ±  0.001  us/op
3. stringTokenizer     avgt    5  0.028 ±  0.002  us/op
4. java8_1             avgt    5  0.077 ±  0.005  us/op
5. java8_2             avgt    5  0.078 ±  0.003  us/op
6. split               avgt    5  0.137 ±  0.009  us/op
7. replaceAll_2        avgt    5  0.302 ±  0.047  us/op
8. replace             avgt    5  0.303 ±  0.034  us/op
9. replaceAll_1        avgt    5  0.351 ±  0.045  us/op


답변

조만간 무언가 가 반복되어야합니다. 다음과 같은 것을 사용하는 것보다 (매우 간단한) 루프를 작성하는 것이 훨씬 간단합니다.split필요한 것보다 훨씬 강력한 합니다.

반드시 루프를 별도의 방법으로 캡슐화하십시오. 예 :

public static int countOccurrences(String haystack, char needle)
{
    int count = 0;
    for (int i=0; i < haystack.length(); i++)
    {
        if (haystack.charAt(i) == needle)
        {
             count++;
        }
    }
    return count;
}

그런 다음 기본 코드에 루프가 필요하지 않지만 루프가 어딘가에 있어야합니다.


답변

나는 Mladen과 비슷한 아이디어를 가지고 있었지만 그 반대는 …

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);


답변

String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();

ReplaceAll ( “.”)은 모든 문자를 대체합니다.

PhiLho의 솔루션 은 ReplaceAll ( “[^.]”, “”)을 사용합니다. [.]는 ‘any character’가 아닌 ‘dot’문자를 나타내므로 이스케이프 할 필요가 없습니다.


답변

내 ‘아이디 오 매틱 원 라이너’솔루션 :

int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();

StringUtils를 사용하는 솔루션이 왜 허용되는지 모릅니다.