我知道我可以将号码与Pattern.compile("\\d*");
但它不能处理长的最小/最大值。
对于与异常相关的性能问题,我不想尝试解析long,除非它真的很长。
if ( LONG_PATTERN.matcher(timestampStr).matches() ) {
long timeStamp = Long.parseLong(timestampStr);
return new Date(timeStamp);
} else {
LOGGER.error("Can't convert " + timestampStr + " to a Date because it is not a timestamp! -> ");
return null;
}
我的意思是我不想要任何try / catch块,而且我不希望像“564654954654464654654567879865132154778”那样长期引发异常,这超出了普通Java长度的范围。
有人有模式来处理原始java类型的这种需求吗? JDK是否提供了自动处理它的东西? Java中是否存在故障安全解析机制?
由于
编辑:请假设“错误的长字符串”不是例外情况。 我不是要求一个基准,我在这里代表一个长期的正则表达式,仅此而已。 我知道正则表达式检查所需的额外时间,但至少我的长解析将始终是常量并且永远不会依赖于“坏长字符串”的百分比
我再也找不到链接了,但StackOverflow上有一个很好的解析基准,它清楚地表明重用编译正则表达式的sams非常快,比抛出一个异常快很多,因此只有一小部分异常可以使系统比使用额外的正则表达式检查要慢。
答案 0 :(得分:10)
long
的最小漏洞为-9,223,372,036,854,775,808
,最大值为9,223,372,036,854,775,807
。所以,最多19位数。因此,\d{1,19}
可以帮助您,可能使用可选的-
,并使用^
和$
来匹配字符串的末尾。
所以大致:
Pattern LONG_PATTERN = Pattern.compile("^-?\\d{1,19}$");
......或类似的东西,并假设你不允许使用逗号(或已经删除它们)。
正如gexicide在评论中指出的那样,上面允许一小部分(比较)无效值范围,例如9,999,999,999,999,999,999
。您可以使用正则表达式进行更复杂的处理,或者只是接受以上内容将清除绝大多数无效数字,从而减少解析异常的数量。
答案 1 :(得分:2)
这个正则表达式可以满足你的需要:
^(-9223372036854775808|0)$|^((-?)((?!0)\d{1,18}|[1-8]\d{18}|9[0-1]\d{17}|92[0-1]\d{16}|922[0-2]\d{15}|9223[0-2]\d{14}|92233[0-6]\d{13}|922337[0-1]\d{12}|92233720[0-2]\d{10}|922337203[0-5]\d{9}|9223372036[0-7]\d{8}|92233720368[0-4]\d{7}|922337203685[0-3]\d{6}|9223372036854[0-6]\d{5}|92233720368547[0-6]\d{4}|922337203685477[0-4]\d{3}|9223372036854775[0-7]\d{2}|922337203685477580[0-7]))$
但此正则表达式不会验证其他符号,例如+
,L
,_
等。如果您需要验证所有可能的Long值,则需要升级此值正则表达式。
答案 2 :(得分:1)
只需捕获NumberFormatException,除非这种情况经常发生。
另一种方法是使用只允许长文字的模式。这种模式可能非常复杂。
第三种方法是首先将数字解析为BigInt。然后,您可以将它与Long.MAX_VALUE和Long.MIN_VALUE进行比较,以检查它是否在long的范围内。但是,这也可能是昂贵的。
另请注意: 解析long很快,它是一种非常优化的方法(例如,尝试在一个步骤中解析两个数字)。应用模式匹配可能比执行解析更加昂贵。解析的唯一问题是抛出NumberFormatException。因此,如果特殊情况不会经常发生,那么只需捕获异常是最好的方法