8

我知道我可以匹配数字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 long 的大小。

有人有一种模式来处理这种对原始 java 类型的需求吗?JDK是否提供了自动处理它的东西?Java中是否有故障安全解析机制?

谢谢


编辑:请假设“坏长字符串”不是例外情况。我不是要一个基准,我来这里是为了一个代表 long 的正则表达式,仅此而已。我知道正则表达式检查所需的额外时间,但至少我的长解析将始终保持不变,并且永远不会依赖于“坏长字符串”的百分比

我找不到链接了,但是 StackOverflow 上有一个很好的解析基准,它清楚地表明重用 sams 编译的正则表达式非常快,比抛出异常快很多,因此只有很小的异常阈值会使系统变慢比附加的正则表达式检查。

4

3 回答 3

15

a 的最小值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. 您可以使用您的正则表达式变得更复杂,或者只是接受上述内容将清除绝大多数无效数字,因此您可以减少您获得的解析异常的数量。

于 2012-06-28T11:06:35.370 回答
3

这个正则表达式应该做你需要的:

^(-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]))$

但是这个正则表达式不会验证额外的符号,比如,+等等。如果你需要验证所有可能的 Long 值,你需要升级这个正则表达式。L_

于 2016-12-13T10:06:33.117 回答
1

只需捕获 NumberFormatException,除非这种情况经常发生。

另一种方法是使用只允许长文字的模式。这种模式可能相当复杂。

第三种方法是首先将数字解析为 BigInt。然后你可以将它与 Long.MAX_VALUE 和 Long.MIN_VALUE 进行比较,以检查它是否在 long 的范围内。然而,这也可能代价高昂。

另请注意:解析 long 非常快,这是一种非常优化的方法(例如,尝试在一个步骤中解析两个数字)。应用模式匹配可能比执行解析成本更高。解析过程中唯一缓慢的是抛出 NumberFormatException。因此,如果异常情况不经常发生,那么简单地捕获异常是最好的方法

于 2012-06-28T11:05:26.760 回答