Java 如何计算字符串中字符的出现次数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/275944/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I count the number of occurrences of a char in a String?
提问by Bart
I have the string
我有字符串
a.b.c.d
I want to count the occurrences of '.' in an idiomatic way, preferably a one-liner.
我想计算 '.' 的出现次数 以惯用的方式,最好是单行。
(Previously I had expressed this constraint as "without a loop", in case you're wondering why everyone's trying to answer without using a loop).
(之前我已将此约束表示为“没有循环”,以防您想知道为什么每个人都试图不使用循环来回答)。
采纳答案by Cowan
My 'idiomatic one-liner' for this is:
我对此的“惯用单行”是:
int count = StringUtils.countMatches("a.b.c.d", ".");
Why write it yourself when it's already in commons lang?
当它已经在公共语言中时为什么要自己写呢?
Spring Framework's oneliner for this is:
Spring Framework 对此的 oneliner 是:
int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");
回答by Jon Skeet
Sooner or later, somethinghas to loop. It's far simpler for you to write the (very simple) loop than to use something like split
which is much more powerful than you need.
迟早,有些事情必须循环。编写(非常简单的)循环比使用split
比您需要的更强大的东西要简单得多。
By all means encapsulate the loop in a separate method, e.g.
无论如何,将循环封装在一个单独的方法中,例如
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;
}
Then you don't need have the loop in your main code - but the loop has to be there somewhere.
然后你不需要在你的主代码中有循环 - 但循环必须在某个地方。
回答by Yonatan Maman
here is a solution without a loop:
这是一个没有循环的解决方案:
public static int countOccurrences(String haystack, char needle, int i){
return ((i=haystack.indexOf(needle, i)) == -1)?0:1+countOccurrences(haystack, needle, i+1);}
System.out.println("num of dots is "+countOccurrences("a.b.c.d",'.',0));
well, there is a loop, but it is invisible:-)
好吧,有一个循环,但它是不可见的:-)
-- Yonatan
——约纳坦
回答by Mladen Prajdic
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\.", "").length();
ReplaceAll(".") would replace all characters.
ReplaceAll(".") 将替换所有字符。
PhiLho's solutionuses ReplaceAll("[^.]",""), which does not need to be escaped, since [.] represents the character 'dot', not 'any character'.
PhiLho 的解决方案使用 ReplaceAll("[^.]",""),它不需要转义,因为 [.] 代表字符“点”,而不是“任何字符”。
回答by PhiLho
I had an idea similar to Mladen, but the opposite...
我有一个类似于姆拉登的想法,但相反......
String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);
回答by Jon Skeet
Okay, inspired by Yonatan's solution, here's one which is purelyrecursive - the only library methods used are length()
and charAt()
, neither of which do any looping:
好的,受 Yonatan 解决方案的启发,这里有一个纯粹递归的方法 - 唯一使用的库方法是length()
and charAt()
,它们都不做任何循环:
public static int countOccurrences(String haystack, char needle)
{
return countOccurrences(haystack, needle, 0);
}
private static int countOccurrences(String haystack, char needle, int index)
{
if (index >= haystack.length())
{
return 0;
}
int contribution = haystack.charAt(index) == needle ? 1 : 0;
return contribution + countOccurrences(haystack, needle, index+1);
}
Whether recursion counts as looping depends on which exact definition you use, but it's probably as close as you'll get.
递归是否算作循环取决于您使用的确切定义,但它可能与您会得到的一样接近。
I don't know whether most JVMs do tail-recursion these days... if not you'll get the eponymous stack overflow for suitably long strings, of course.
我不知道这些天大多数 JVM 是否进行尾递归......如果不是,你会得到适当长字符串的同名堆栈溢出,当然。
回答by tcurdt
While methods can hide it, there is no way to count without a loop (or recursion). You want to use a char[] for performance reasons though.
虽然方法可以隐藏它,但没有循环(或递归)就无法计数。出于性能原因,您想使用 char[] 。
public static int count( final String s, final char c ) {
final char[] chars = s.toCharArray();
int count = 0;
for(int i=0; i<chars.length; i++) {
if (chars[i] == c) {
count++;
}
}
return count;
}
Using replaceAll (that is RE) does not sound like the best way to go.
使用 replaceAll(即 RE)听起来并不是最好的方法。
回答by Tom Hawtin - tackline
Inspired by Jon Skeet, a non-loop version that wont blow your stack. Also useful starting point if you want to use the fork-join framework.
受 Jon Skeet 的启发,这是一个不会让您的堆栈爆炸的非循环版本。如果您想使用 fork-join 框架,这也是一个有用的起点。
public static int countOccurrences(CharSequeunce haystack, char needle) {
return countOccurrences(haystack, needle, 0, haystack.length);
}
// Alternatively String.substring/subsequence use to be relatively efficient
// on most Java library implementations, but isn't any more [2013].
private static int countOccurrences(
CharSequence haystack, char needle, int start, int end
) {
if (start == end) {
return 0;
} else if (start+1 == end) {
return haystack.charAt(start) == needle ? 1 : 0;
} else {
int mid = (end+start)>>>1; // Watch for integer overflow...
return
countOccurrences(haystack, needle, start, mid) +
countOccurrences(haystack, needle, mid, end);
}
}
(Disclaimer: Not tested, not compiled, not sensible.)
(免责声明:未经测试,未经编译,不合理。)
Perhaps the best (single-threaded, no surrogate-pair support) way to write it:
也许是最好的(单线程,没有代理对支持)的写法:
public static int countOccurrences(String haystack, char needle) {
int count = 0;
for (char c : haystack.toCharArray()) {
if (c == needle) {
++count;
}
}
return count;
}
回答by Piskvor left the building
Somewhere in the code, something has to loop. The only way around this is a complete unrolling of the loop:
在代码中的某个地方,某些东西必须循环。解决这个问题的唯一方法是完全展开循环:
int numDots = 0;
if (s.charAt(0) == '.') {
numDots++;
}
if (s.charAt(1) == '.') {
numDots++;
}
if (s.charAt(2) == '.') {
numDots++;
}
...etc, but then you're the one doing the loop, manually, in the source editor - instead of the computer that will run it. See the pseudocode:
...等,但是您是在源代码编辑器中手动执行循环的人 - 而不是将运行它的计算机。见伪代码:
create a project
position = 0
while (not end of string) {
write check for character at position "position" (see above)
}
write code to output variable "numDots"
compile program
hand in homework
do not think of the loop that your "if"s may have been optimized and compiled to
回答by Stephen Denne
Here is a slightly different style recursion solution:
这是一个稍微不同风格的递归解决方案:
public static int countOccurrences(String haystack, char needle)
{
return countOccurrences(haystack, needle, 0);
}
private static int countOccurrences(String haystack, char needle, int accumulator)
{
if (haystack.length() == 0) return accumulator;
return countOccurrences(haystack.substring(1), needle, haystack.charAt(0) == needle ? accumulator + 1 : accumulator);
}
回答by Peter Lawrey
A shorter example is
一个较短的例子是
String text = "a.b.c.d";
int count = text.split("\.",-1).length-1;