2 回答

TA贡献1821条经验 获得超6个赞
据我所知,答案是否定的,没有其他库可以将2018-01-02T12:34:56+00:00"(ISO 8601 格式)等字符串解析为OffsetDateTime对象。如果存在的话,我会期望听到或读到它。
我对下一点如履薄冰,但我也认为标准库(AKA java.time)足够高效,并且可能与您期望的一样快。
编辑:我很好奇并编写了自己的 parse 方法,看看我是否能够胜过 one-arg OffsetDateTime.parse。我曾是。我自己的方法(以下来源)没有内置方法的灵活性,它只接受标准格式的大量变体中的一个,这可能是它在性能方面的强项。解析你的字符串一百万次需要:
1.034 秒使用OffsetDateTime.parse
0.117秒用我自己的方法
这不是推荐!我可能永远不会使用我自己的方法。出于绝大多数目的,维护负担是不值得的。如果有一天出现了 ISO 8601 的不同变体,您将遇到昂贵的支持问题和错误修复。
我的方法很简单:
private static final OffsetDateTime parse(String s) {
char offsetSign;
if (s.length() != 25
|| s.charAt(4) != '-'
|| s.charAt(7) != '-'
|| s.charAt(10) != 'T'
|| s.charAt(13) != ':'
|| s.charAt(16) != ':'
|| ((offsetSign = s.charAt(19)) != '+' && offsetSign != '-')
|| s.charAt(22) != ':') {
throw new IllegalArgumentException();
}
int offsetHours = Integer.parseInt(s.substring(20, 22));
int offsetMinutes = Integer.parseInt(s.substring(23, 25));
if (offsetSign == '-') {
offsetHours = -offsetHours;
offsetMinutes = -offsetMinutes;
}
return OffsetDateTime.of(Integer.parseInt(s.substring(0, 4)),
Integer.parseInt(s.substring(5, 7)),
Integer.parseInt(s.substring(8, 10)),
Integer.parseInt(s.substring(11, 13)),
Integer.parseInt(s.substring(14, 16)),
Integer.parseInt(s.substring(17, 19)),
0,
ZoneOffset.ofHoursMinutes(offsetHours, offsetMinutes));
}
我知道代码中的错误。我认为不值得彻底测试并修复此答案的错误,因为它不太可能对性能产生太大影响。

TA贡献1856条经验 获得超11个赞
每次解析不到一毫秒,您不必担心优化解析OffsetDateTime
。当然,你必须有更大的鱼来炸。
细节
让我们尝试一个小基准测试。
警告:微基准是出了名的不可靠。但希望这能让我们接近现实的理解。
警告:我匆匆写下这段代码和这篇文章。请仔细检查我的工作。
在我试图避免 JVM 优化运行时的微弱尝试中,我使用了 31 个不同的值,一个用于 1 月份的每一天。我将这些重复一千次以获得 31,000 个列表。然后我洗牌了。
尽管如此,我的结果表明在运行时进行了大量优化。每次解析的纳秒数因循环数而变化很大。
100_000 次循环 = 每次解析 1,573 纳秒(1 微秒)
10_000 = 4,243
1_000 = 10,177
100 = 31,125
1 = 每次解析 693,687 纳秒。(693 微秒,超过半毫秒)。
我使用了 Azul Systems 的 Java 11 JVM Zulu产品,这是一个基于 OpenJDK 版本 11.0.2 的实现。在 MacBook Pro(Retina,15 英寸,2013 年末)、2.3 GHz Intel Core i7、16 GB 1600 MHz DDR3 上运行。
结果总结:
我的结论:
不要担心解析您的
OffsetDateTime
输入字符串。您可能会陷入过早优化的陷阱。
代码。
System.out.println( "INFO - Starting the OffsetDateTime parsing benchmark." );
List < String > inputsShort = new ArrayList <>( 31 );
inputsShort.add( "2018-01-01T12:34:56+00:00" );
inputsShort.add( "2018-01-02T12:34:56+00:00" );
inputsShort.add( "2018-01-03T12:34:56+00:00" );
inputsShort.add( "2018-01-04T12:34:56+00:00" );
inputsShort.add( "2018-01-05T12:34:56+00:00" );
inputsShort.add( "2018-01-06T12:34:56+00:00" );
inputsShort.add( "2018-01-07T12:34:56+00:00" );
inputsShort.add( "2018-01-08T12:34:56+00:00" );
inputsShort.add( "2018-01-09T12:34:56+00:00" );
inputsShort.add( "2018-01-10T12:34:56+00:00" );
inputsShort.add( "2018-01-11T12:34:56+00:00" );
inputsShort.add( "2018-01-12T12:34:56+00:00" );
inputsShort.add( "2018-01-13T12:34:56+00:00" );
inputsShort.add( "2018-01-14T12:34:56+00:00" );
inputsShort.add( "2018-01-15T12:34:56+00:00" );
inputsShort.add( "2018-01-16T12:34:56+00:00" );
inputsShort.add( "2018-01-17T12:34:56+00:00" );
inputsShort.add( "2018-01-18T12:34:56+00:00" );
inputsShort.add( "2018-01-19T12:34:56+00:00" );
inputsShort.add( "2018-01-20T12:34:56+00:00" );
inputsShort.add( "2018-01-21T12:34:56+00:00" );
inputsShort.add( "2018-01-22T12:34:56+00:00" );
inputsShort.add( "2018-01-23T12:34:56+00:00" );
inputsShort.add( "2018-01-24T12:34:56+00:00" );
inputsShort.add( "2018-01-25T12:34:56+00:00" );
inputsShort.add( "2018-01-26T12:34:56+00:00" );
inputsShort.add( "2018-01-27T12:34:56+00:00" );
inputsShort.add( "2018-01-28T12:34:56+00:00" );
inputsShort.add( "2018-01-29T12:34:56+00:00" );
inputsShort.add( "2018-01-30T12:34:56+00:00" );
inputsShort.add( "2018-01-31T12:34:56+00:00" );
int loops = 100; // 100_000=1,573 nanos each parse. 10_000=4,243. 1_000=10,177. 100=31,125. 1=693,687 nanos each parse.
List < String > inputs = new ArrayList <>( inputsShort.size() * loops );
for ( int i = 1 ; i <= loops ; i++ ) {
inputs.addAll( inputsShort );
}
Collections.shuffle( inputs );
//System.out.println( inputs );
long start = System.nanoTime();
for ( String input : inputs ) {
OffsetDateTime odt = OffsetDateTime.parse( input );
}
long stop = System.nanoTime();
long nanosPerParse = ( ( stop - start ) / inputs.size() );
System.out.println( "INFO: nanosPerParse: " + nanosPerParse + " for a count of: " + inputs.size() + "." );
添加回答
举报