JAVA 高效判断字符串的字符个数

本文介绍了一个简单的Java程序,用于统计给定字符串中每个字符出现的次数,并打印出每个非零出现次数的字符及其对应的频率。该程序使用了数组来记录ASCII码范围内的字符计数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public static void main(String[] args) {

    	int max = 0;

    	int[] count = new int[255];

    	char ch;

    	String input = "QEQSERTWR145657ABCsfgsdEYP[YLYULYfgDEFsdgfsgtutjtyktEDYERTYEEAERYTEYERALUILYUILO";



    	for(int i = 0; i < input.length(); i++) {

    	    int cou = ++count[(int)input.charAt(i)];

    	    if(cou >= max) {

    	        max = cou;

    	        ch = input.charAt(i);

    	    }

    	}

    	for(int i=0;i<count.length;i++){

    		if(count[i]==0) continue;

    		System.out.println(String.valueOf((char)i)+" "+count[i]);

    	}

}

<think>我们被要求判断字符串是否为数(包括整数和小数)。根据引用内容,我们可以采用正则表达式的方法。引用[1]和引用[2]都提供了使用正则表达式判断的方法。其中,引用[1]的方法比较简单,直接使用一个正则表达式匹配整数和小数。引用[2]则提供了更详细的分类,可以分别判断整数和浮点数(小数)。根据用户需求,我们只需要判断是否为数(包括整数和小数),不需要区分整数和小数,所以我们可以采用一个正则表达式同时匹配整数和小数。观察引用[1]的正则表达式:`[0-9]*\\.?[0-9]+`,这个表达式可以匹配:-整数:例如"123"(注意,这里要求至少有一个数,所以不能为空)-小数:例如"123.45",".45"(注意,这个正则表达式可以匹配以小数点开头的小数,但是不能匹配以小数点结尾的,比如"123.",因为小数点后面要求至少一个数)但是,引用[1]的正则表达式没有考虑正负号(+、-)的情况。引用[2]中判断(包括整数和小数)的正则表达式为:`"^(-|\\+)?\\d+(\\.\\d+)?$"`,这个表达式可以匹配:-可选的正负号(+或-)-整数部分:至少一个数(所以不能只有符号)-可选的小数部分:小数点后至少一个数(所以不能以小数点结尾)但是,这个表达式不能匹配像".45"这样的小数(因为整数部分要求至少一个数)。我们可能需要一个能够匹配以下情况的表达式:-整数:如"123","+123","-123"-小数:如"123.45","+123.45","-123.45",".45","+.45","-.45"-但不能匹配只有符号的字符串(如"+"、"-")或小数点(".")另外,引用[3]提供了一种不使用正则表达式的方法,但只能判断整数(它检查每个字符是否为数,所以不能有符号和小数点)。综合需求,我们可以设计一个正则表达式来匹配整数和小数,包括正负号以及小数点开头或整数部分开头的情况。常见的匹配数(整数和小数)的正则表达式可以写成:`^[-+]?[0-9]*\\.?[0-9]+$`这个表达式可以匹配:整数:123,+123,-123小数:123.45,.45,+.45,-.45但是,这个表达式也会匹配只有一个小数点的情况吗?不会,因为`[0-9]*\\.?[0-9]+`要求最后必须有一个或多个数,所以至少有一个数。但是,这个表达式有一个问题:它允许整数部分为空和小数点前面为空,但是不允许没有小数点时整数部分为空(因为整个数部分不能为空)。然而,它不能匹配"123."(小数点结尾)这种情况。实际上,我们通常认为"123."是整数123,但有时可能希望接受它。不过,严格来说,如果字符串是"123.",它并不是一个标准的小数表示,我们可以要求必须写成整数形式(即去掉末尾的小数点)或写成小数形式(小数点后必须有数)。另外,我们还要考虑没有整数部分的小数(如.45),这在某些情况下是允许的。但是,注意:引用[2]中判断浮点数的方法更正后的正则表达式是`[+-]?[0-9]+\\.([0-9]+)`,这个要求整数部分至少有一个数,小数部分至少有一个数,所以不能匹配".45"(因为整数部分至少一个数),也不能匹配"123."(因为小数部分至少一个数)。因此,我们需要明确需求:用户是否接受以小数点开头的小数(如.45)?是否接受以小数点结尾的字符串(如123.)?根据一般情况,我们通常要求小数部分如果有小数点,则小数点后必须有数,整数部分可以没有数(即.45是允许的),但整数部分有数时,小数点后可以没有数吗(即123.)?这通常不被认为是一个合法的数字符串。所以,我们通常要求:-整数部分:可以没有(即小数点开头),如果有,可以是0个或多个数(但注意,如果整数部分为空,那么小数点必须存在,因为否则就变成了一个空字符串)-小数部分:可以没有(即没有小数点),如果有,小数点后必须有至少一个数。因此,我们可以这样设计:`^[-+]?(([0-9]*\\.?[0-9]+)|([0-9]+\\.?[0-9]*))$`但是这个表达式会匹配单独的小数点(因为第一部分`[0-9]*`可以匹配0个数,`\\.?`可以匹配0个小数点,然后`[0-9]+`要求至少一个数,所以没有小数点的时候,整数部分至少要有一个数?不对,这个表达式实际上允许两种情况:1.整数部分可以没有(为0个),但必须有小数部分(即小数点后至少一个数)——对应第一种情况:`[0-9]*\\.?[0-9]+`,当没有整数部分时,必须有一个小数点和至少一个数(即.45)2.整数部分至少一个数,小数部分可有可无(即123或123.)——但注意,这里第二种情况是`[0-9]+\\.?[0-9]*`,它允许123.,因为小数部分可以0个数(即123.匹配了整数部分123,小数点,小数部分0个数)我们并不希望匹配123.这样的字符串(因为小数部分为空),所以需要避免这种情况。因此,更精确的写法是:整数部分可以没有(即.45),小数部分也可以没有(即整数),但如果有小数点,则后面必须跟至少一个数。所以,我们可以写成:`^[-+]?(([0-9]+)|(\\.[0-9]+)|([0-9]+\\.[0-9]+))$`这个表达式匹配:整数:[-+]?[0-9]+(如123,+123,-123)纯小数(无整数部分):[-+]?\\.[0-9]+(如.45,+.45,-.45)整数部分和小数部分都有:[-+]?[0-9]+\\.[0-9]+(如123.45)但是,这个表达式不能匹配整数0(因为0也是整数),但可以匹配0.45。但是,整数部分如果是0呢?比如0.45,它会被第三种情况匹配。但是整数0呢?第一种情况要求至少一个数,所以0可以匹配(因为0是一个或多个数)。然而,这个表达式不能匹配0.(后面没有数)或者.0(但.0是可以匹配的,因为属于第二种情况)。但是,我们不允许0.这样的字符串,因为小数点后没有数。另外,这个表达式也没有匹配0(整数0)和0.0(小数)等情况。实际上,这个表达式已经可以覆盖大多数情况,但是有没有更简洁的方式?另一种常见的写法是:`^[-+]?[0-9]*\\.?[0-9]+$`,这个表达式可以匹配:-整数:123->123(整数部分有数,小数部分没有,但注意:表达式中的`[0-9]*`匹配了123,`\\.?`匹配0次,`[0-9]+`匹配123,但实际上整个表达式要求最后必须有一个或多个数,所以整数部分必须有?不对,`[0-9]*`可以匹配0个,然后`\\.?`匹配0个,然后`[0-9]+`匹配数,所以整数部分可以没有数,但是整个数必须至少有一个数(由最后的`[0-9]+`提供)。因此,它不能匹配以小数点开头的数(因为小数点需要匹配,而表达式中的`\\.?`后面跟着`[0-9]+`,所以如果字符串是".45",那么`[0-9]*`匹配0个数,`\\.?`匹配小数点,`[0-9]+`匹配45,所以整个匹配成功。但是,这个表达式也可以匹配123.45:整数部分123,小数点,小数部分45。同样,它也可以匹配123:整数部分123,小数部分没有(但注意,这里`\\.?`匹配0次,然后`[0-9]+`匹配123,所以整个123被最后的`[0-9]+`匹配了)。但是,这个表达式会匹配123.吗?不会,因为`\\.?`匹配了小数点(1次),然后要求后面必须有至少一个数(由`[0-9]+`),所以123.不能匹配。但是,这个表达式有一个问题:它允许整数部分为空,但是当整数部分为空时,小数点必须存在(因为如果整数部分为空,又没有小数点,那么整个表达式变成了`[0-9]+`,但这时它匹配的整数部分为空,然后没有小数点,然后要求后面有数,所以整个字符串就是数,即整数。但是,整数部分为空且没有小数点,那么整个表达式就要求至少一个数,所以实际上这个表达式也可以匹配整数(即整数部分不为空的情况和整数部分为空但小数部分不为空的情况?不对,整数部分为空且没有小数点,那么表达式就变成了`[0-9]+`,也就是整数,所以整数也被匹配了。实际上,这个表达式可以匹配所有整数和所有小数(包括以小数点开头的),但是不能匹配以小数点结尾的。但是,这个表达式会匹配一个空字符串吗?不会,因为最后的`[0-9]+`要求至少一个数。那么,这个表达式可以写成:`^[-+]?[0-9]*\\.?[0-9]+$`,但是它有一个问题:它匹配了像“123”这样的整数,但是实际上,在匹配整数时,整数部分(由`[0-9]*`匹配)和后面的`[0-9]+`会重叠。例如,字符串"123":[-+]?:没有匹配[0-9]*:匹配了0个数(因为*是贪婪的?实际上它会匹配尽可能多的,所以它会匹配整个123,然后后面\\.?没有匹配,然后[0-9]+要求至少一个数,但是整个字符串已经匹配完了,所以这里会有问题吗?不会,因为正则表达式引擎会尝试不同的方式,但实际上这里*会匹配尽可能多的,所以它匹配了123,然后后面没有小数点了,然后要求至少一个数,但已经匹配完了,所以无法满足后面的[0-9]+。所以这个表达式不能匹配整数?实际上,这个表达式不能匹配整数,因为表达式中的`[0-9]*\\.?[0-9]+`要求最后必须有一部分数(即[0-9]+)不能被前面的*匹配掉?但是,正则表达式引擎会回溯:当*匹配了123后,后面没有小数点和数了,所以无法匹配[0-9]+,那么它会回溯:让*只匹配12,然后后面\\.?匹配0次,然后[0-9]+匹配3,这样整个字符串就匹配了。所以实际上是可以匹配整数的。但是,这样写可能会有效率问题(因为回溯),而且不够直观。因此,我们采用另一种写法:`^[-+]?(\\.\\d+|\\d+\\.?\\d*)$`这个表达式分为两种情况:1.\\.\\d+匹配以小数点开头的小数(如.45)2.\\d+\\.?\\d*匹配整数部分至少一个数,后面可以有小数点也可以没有,如果有小数点,则后面可以跟0个或多个数(所以可以匹配整数:123;也可以匹配123.45,也可以匹配123.->但这里123.会被匹配,因为小数部分0个数,即允许以小数点结尾?)我们不允许以小数点结尾(即123.),所以第二种情况需要修改:要求如果有小数点,则后面必须至少有一个数。所以不能使用`\\d*`,而应该改为:如果有小数点,则后面必须至少一个数,没有小数点则结束。所以,我们改为:`^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$`这个表达式:第一种情况:\\.\\d+匹配以小数点开头的小数第二种情况:\\d+(\\.\\d+)?匹配整数(只有整数部分)或者整数部分和小数部分(小数部分必须有小数点且小数点后至少一个数)这个表达式不会匹配123.,因为第二种情况中,如果出现小数点,后面必须跟着至少一个数。所以,我们可以使用这个正则表达式:`^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$`但是,这个表达式可以匹配:.45->匹配(第一种情况)123->匹配(第二种情况:整数)123.45->匹配(第二种情况:整数+小数)+123.45->匹配-123.45->匹配+.45->匹配但是,它不能匹配像“123.”这样的字符串,符合要求。另外,它也不能匹配只有符号的字符串(如“+”、“-”),因为两种情况都要求必须有数。但是,这个表达式有一个小问题:整数部分不能为0?不对,整数部分可以是0(比如“0”、“0.45”),因为\d+可以匹配0。所以,我们使用这个正则表达式。在Java中,我们可以这样写:Patternpattern=Pattern.compile("^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$");但是,注意,这个正则表达式中的`\d`在Java字符串中需要转义,所以写成字符串时应该是:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";但是,在Java中,我们需要对每个反斜杠进行转义,所以变成:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";->不对,因为`\d`在Java字符串中需要写成`\\d`,所以:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";实际上,我们写成字符串时,需要将每个反斜杠再转义一次,即:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";应该改为:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";但是,这样写会出错,因为字符串中的`\.`会被认为是转义点,实际上我们想要的是正则中的`\.`(匹配小数点),所以我们需要用两个反斜杠表示一个反斜杠:因此,正确的Java字符串应该是:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";但是,我们注意到,引用[1]和[2]中都是使用两个反斜杠的,所以:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";在Java中应该写成:Stringregex="^[-+]?(\\\\.\\\\d+|\\\\d+(\\\\.\\\\d+)?)$";这样写显然不对,因为过度转义了。实际上,在正则表达式中,小数点用`\.`表示,但在Java字符串中,我们需要写成`\\\\.`?不对,应该是:`\.`在Java字符串中要写成`\\\\.`吗?不对,应该是两个反斜杠:因为一个反斜杠在Java字符串中是转义符,所以我们需要用两个反斜杠表示一个反斜杠,所以正则中的`\.`在Java字符串中写成`\\\\.`?不对,正则中的`\.`实际上就是匹配小数点,而正则中的反斜杠在Java字符串中需要用两个反斜杠表示,所以`\.`在Java字符串中写成`"\\\\."`。因此,整个正则表达式在Java字符串中应该写成:Stringregex="^[-+]?(\\\\.\\\\d+|\\\\d+(\\\\.\\\\d+)?)$";但是,这样写太复杂,而且容易出错。我们可以使用更清晰的方式:我们注意到,在正则表达式中,小数点可以不用转义,直接写`.`也可以,因为在一个方括号外的小数点通常表示它自己。但是,在正则中,小数点有特殊含义(匹配任意字符),所以我们必须转义。不过,在字符类(方括号内)的小数点不需要转义。因此,为了避免混淆,我们可以使用:Stringregex="^[-+]?([.]\\d+|\\d+([.]\\d+)?)$";这样,在Java字符串中,我们只需要写:Stringregex="^[-+]?([.]\\d+|\\d+([.]\\d+)?)$";或者,我们可以使用:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";->在Java字符串中,我们需要将每个反斜杠变成两个反斜杠:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";不对,应该是:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";实际上,正确的写法是:Stringregex="^[-+]?(\\.\\d+|\\d+(\\.\\d+)?)$";因为:正则表达式中的`\.`表示小数点,在Java字符串中,我们需要用两个反斜杠表示一个反斜杠,所以`\.`写成`\\\\.`,而`\d`写成`\\\\d`。所以,整个表达式写成:Stringregex="^[-+]?(\\\\.\\\\d+|\\\\d+(\\\\.\\\\d+)?)$";这样写很麻烦,而且容易出错。因此,我们可以选择使用单引号包围的小数点(即用字符类[.])或者直接使用不带转义的点(但这样不安全,因为点可以匹配任意字符)。所以,为了避免转义带来的困扰,我们可以使用字符类[.]来表示小数点。因此,我们写成:Stringregex="^[-+]?([.]\\d+|\\d+([.]\\d+)?)$";在Java字符串中,这个表达式不需要额外的反斜杠转义(因为方括号内的点就是小数点,不需要转义),所以:Stringregex="^[-+]?([.]\\d+|\\d+([.]\\d+)?)$";现在,我们写一个方法:publicstaticbooleanisNumeric(Stringstr){if(str==null||str.isEmpty()){returnfalse;}Patternpattern=Pattern.compile("^[-+]?([.]\\d+|\\d+([.]\\d+)?)$");Matchermatcher=pattern.matcher(str);returnmatcher.matches();}但是,我们还要考虑一种情况:字符串中可能包含空格?我们的正则表达式要求整个字符串匹配,所以如果有空格,就不会匹配。所以如果字符串有空格,我们需要先去掉空格?根据需求,通常我们不考虑前后空格,所以如果允许空格,应该先trim。但题目没有要求,所以我们按照严格匹配,不允许空格。另外,我们还要考虑数中可能包含千分位分隔符(如1,000.23)?但题目要求是整数和小数,所以不考虑千分位。因此,我们写一个完整的方法。但是,我们也可以参考引用[2]中的方法,它提供了一个判断的方法(包括整数和小数),我们稍作修改。我们也可以采用引用[1]的方法,并改进以支持正负号。引用[1]的正则表达式是:`"[0-9]*\\.?[0-9]+"`,不支持正负号,我们可以加上正负号:Stringregex="[-+]?[0-9]*\\.?[0-9]+";但是,这个表达式会匹配123.,因为123.会被这样匹配:整数部分123匹配[0-9]*(实际上[0-9]*匹配123),然后\\.?匹配小数点,然后[0-9]+匹配后面的部分,但是后面没有数了,所以匹配失败。但是,正则表达式引擎会尝试回溯:让[0-9]*只匹配12,然后\\.?匹配.,然后[0-9]+匹配3,所以整个字符串123.就被匹配了。但是,我们不想匹配123.,所以这个表达式有问题。因此,我们采用之前设计的正则表达式:`^[-+]?([.]\\d+|\\d+([.]\\d+)?)$`。现在,我们写一个完整的方法。注意:这个正则表达式不能匹配像“0”这样的单个0,但是可以匹配,因为`\d+`可以匹配0。测试用例:"123"->true"123.45"->true".45"->true"0"->true"0.0"->true"0."->false"."->false"+123"->true"-123"->true"+.45"->true"-.45"->true"123."->false"+"->false"-"->false""->false但是,有一个问题:这个正则表达式会匹配像“0123”这样的数吗?会,因为整数部分允许以0开头。通常,数字符串中允许前导0(如0123),这被视为123。如果不想允许前导0,我们需要另外处理。但题目没有要求,所以我们可以接受。如果不想接受前导0,那么整数部分就不能以0开头(除非是0本身)。但这样会增加复杂度,所以这里不做要求。因此,我们采用上述正则表达式。代码实现:importjava.util.regex.Pattern;importjava.util.regex.Matcher;publicclassNumericChecker{publicstaticbooleanisNumeric(Stringstr){if(str==null||str.isEmpty()){returnfalse;}Patternpattern=Pattern.compile("^[-+]?([.]\\d+|\\d+([.]\\d+)?)$");Matchermatcher=pattern.matcher(str);returnmatcher.matches();}}但是,注意:正则表达式中的`\d`等价于[0-9],所以也可以写成[0-9]以避免转义问题?但是这里我们使用了[.],所以整体上我们避免了在Java字符串中写多个反斜杠。另外,我们也可以使用`String.matches`方法,这样更简洁:publicstaticbooleanisNumeric(Stringstr){if(str==null||str.isEmpty()){returnfalse;}returnstr.matches("[-+]?([.]\\d+|\\d+([.]\\d+)?)");}因为String.matches方法要求整个字符串匹配,所以不需要^和$(它隐含了整个字符串)。所以,我们可以这样写:publicstaticbooleanisNumeric(Stringstr){returnstr!=null&&str.matches("[-+]?([.]\\d+|\\d+([.]\\d+)?)");}但是,注意:当字符串为空时,str.matches会返回false,因为空字符串不匹配这个表达式。所以我们可以省略空字符串的检查。因此,最终方法如下:publicstaticbooleanisNumeric(Stringstr){returnstr!=null&&str.matches("[-+]?([.]\\d+|\\d+([.]\\d+)?)");}但是,我们还要测试一下。比如,字符串"0"可以匹配吗?"0":满足第二种情况:\\d+(0是一个数),后面没有小数部分,所以匹配。所以,我们使用这个方法。另外,引用[2]中也有一个判断的方法,它使用的正则表达式是:"^(-|\\+)?\\d+(\\.\\d+)?$",这个表达式不能匹配以小数点开头的数(如.45),所以我们的方法更全面。因此,我们按照上面的方法实现。下面,我们提供一个完整的示例代码。</think>在Java中,判断字符串是否为数(包括整数和小数)可以通过正则表达式高效实现。以下是完整解决方案: ### 方法实现 ```java import java.util.regex.Pattern; public class NumericChecker { /** * 判断字符串是否为数(整数或小数) * @param str 待检测字符串 * @return true: 是数, false: 不是数 */ public static boolean isNumeric(String str) { if (str == null || str.isEmpty()) { return false; } // 正则解释:匹配可选正负号,支持两种格式: // 1. 纯小数(如.45, -.23) // 2. 整数或带小数部分(如123, 123.45) String regex = "[-+]?([.]\\d+|\\d+([.]\\d+)?)"; return Pattern.matches(regex, str); } } ``` ### 正则表达式详解 - `[-+]?`:可选正负号(匹配`+`、`-`或不出现) - `([.]\\d+|\\d+([.]\\d+)?)`:分两种情况 1. `[.]\\d+`:纯小数(如`.45`, `-.23`) 2. `\\d+([.]\\d+)?`:整数(`123`)或标准小数(`123.45`) ### 测试用例 ```java public static void main(String[] args) { System.out.println(isNumeric("123")); // true (整数) System.out.println(isNumeric("-45.67")); // true (负小数) System.out.println(isNumeric(".89")); // true (纯小数) System.out.println(isNumeric("+0.5")); // true (正小数) System.out.println(isNumeric("0")); // true (整数0) System.out.println(isNumeric("abc")); // false System.out.println(isNumeric("123.")); // false (小数点结尾) System.out.println(isNumeric("12.3.4")); // false (多个小数点) System.out.println(isNumeric("")); // false (空字符串) } ``` ### 关键说明 1. **边界处理**:明确拒绝`null`和空字符串 2. **严格匹配**: - 禁止`123.`格式(小数点后必须有数) - 允许`.5`格式(整数部分可省略) - 正确处理正负号 3. **性能优化**:使用预编译的`Pattern.matches()`方法[^1][^2] 此实现覆盖了整数、正负小数、纯小数(无整数部分)等所有合法数格式,同时排除了非法格式(如多个小数点、单独的正负号等)。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值