10

解析 YYYYMMdd 日期时,例如 2012 年 4 月 5 日的 20120405,最快的方法是什么?

int year = Integer.parseInt(dateString.substring(0, 4));
int month = Integer.parseInt(dateString.substring(4, 6));
int day = Integer.parseInt(dateString.substring(6));

对比

int date = Integer.parseInt(dateString)
year = date / 10000;
month = (date % 10000) / 100; 
day = date % 100;

mod 10000 for month 是因为 mod 10000 导致 MMdd 并且结果 / 100 是 MM

在第一个示例中,我们执行 3 个字符串操作和 3 个“解析为 int”,在第二个示例中,我们通过模数做了很多事情。

什么更快?有没有更快的方法?

4

6 回答 6

33
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
Date date = format.parse("20120405");
于 2012-04-04T15:15:14.627 回答
14

正如您在下面看到的,仅当您查看数百万次迭代时,日期处理的性能才相关。相反,您应该选择易于阅读和维护的解决方案。

尽管您可以使用SimpleDateFormat,但它不是可重入的,因此应避免使用。最好的解决方案是使用出色的 Joda 时间课程:

private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder()
     .appendYear(4,4).appendMonthOfYear(2).appendDayOfMonth(2).toFormatter();
...
Date date = DATE_FORMATTER.parseDateTime(dateOfBirth).toDate();

如果我们谈论的是您的数学函数,首先要指出的是我已经修复了您的数学代码中的错误。这就是手工操作的问题。也就是说,处理一次字符串的那些将是最快的。快速测试运行表明:

year = Integer.parseInt(dateString.substring(0, 4));
month = Integer.parseInt(dateString.substring(4, 6));
day = Integer.parseInt(dateString.substring(6));

大约需要 800 毫秒,而:

int date = Integer.parseInt(dateString);
year = date / 10000;
month = (date % 10000) / 100; 
day = date % 100;
total += year + month + day;

大约需要 400 毫秒。

但是……再一次……您需要考虑到这是在1000 万次迭代之后。这是过早优化的完美示例。我会选择最易读和最容易维护的那个。这就是为什么 Joda time 的答案是最好的。

于 2012-04-04T15:21:06.937 回答
5

我做了一个快速的基准测试,两种方法都被执行了 100 万次。结果清楚地表明模数方法要快得多,正如 Dilum Ranatunga 预测的那样。

t.startTiming();
for(int i=0;i<1000000;i++) {
    int year = Integer.parseInt(dateString.substring(0, 4));
    int month = Integer.parseInt(dateString.substring(4, 6));
    int day = Integer.parseInt(dateString.substring(6));
}
t.stopTiming();
System.out.println("First method: "+t.getElapsedTime());

Time t2 = new Time();
t2.startTiming();
for(int i=0;i<1000000;i++) {
    int date = Integer.parseInt(dateString);
    int y2 = date / 1000;
    int m2 = (date % 1000) / 100;
    int d2 = date % 10000;
}
t2.stopTiming();
System.out.println("Second method: "+t2.getElapsedTime());

结果不会说谎(以毫秒为单位)。

First method: 129
Second method: 53
于 2012-04-04T15:24:06.160 回答
3

第二个肯定会更快,一旦您更改mod%添加缺少的分号并修复year计算中的除数。也就是说,我发现很难想象这是一个瓶颈的应用程序。你有多少次将YYYYMMdd日期解析到它们的组件中,而不需要验证它们?

于 2012-04-04T15:14:10.687 回答
3

怎么样(但它会解析一个无效的日期而不说什么......):

public static void main(String[] args) throws Exception {
    char zero = '0';
    int yearZero = zero * 1111;
    int monthAndDayZero = zero * 11;
    String s = "20120405";
    int year = s.charAt(0) * 1000 + s.charAt(1) * 100 + s.charAt(2) * 10 + s.charAt(3) - yearZero;
    int month = s.charAt(4) * 10 + s.charAt(5) - monthAndDayZero;
    int day = s.charAt(6) * 10 + s.charAt(7) - monthAndDayZero;
}

使用 100,000 次迭代预热和 10,000,000 次定时迭代进行快速而肮脏的基准测试,我得到:

  • 第一种方法需要 700 毫秒
  • 第二种方法需要 350 毫秒
  • 我的方法是 10 毫秒。
于 2012-04-04T15:15:21.277 回答
0

我相信mod方法会更快。通过调用该函数,您可以在堆栈上创建变量和位置实例并创建更重的解决方案。

Mod 是标准的数学运算符,可能非常优化。

但正如 Hunter McMillen 所说“你应该看看 Calendar 类 API”

于 2012-04-04T15:14:35.973 回答