Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么在Java中将字符串解析为日期很慢?我们能加速吗?_Java_Date_Simpledateformat_Date Parsing - Fatal编程技术网

为什么在Java中将字符串解析为日期很慢?我们能加速吗?

为什么在Java中将字符串解析为日期很慢?我们能加速吗?,java,date,simpledateformat,date-parsing,Java,Date,Simpledateformat,Date Parsing,我正在读取一个包含日期的文本文件,我想在java中将表示日期的字符串解析为日期对象。我注意到操作很慢。为什么?有什么办法可以加速吗? 我的文件看起来像: 2012-05-02 12:08:06:950, secondColumn, thirdColumn 2012-05-02 12:08:07:530, secondColumn, thirdColumn 2012-05-02 12:08:08:610, secondColumn, thirdColumn 我逐行读取文件,然后从每行获取日期字符

我正在读取一个包含日期的文本文件,我想在java中将表示日期的字符串解析为日期对象。我注意到操作很慢。为什么?有什么办法可以加速吗? 我的文件看起来像:

2012-05-02 12:08:06:950, secondColumn, thirdColumn
2012-05-02 12:08:07:530, secondColumn, thirdColumn
2012-05-02 12:08:08:610, secondColumn, thirdColumn
我逐行读取文件,然后从每行获取日期
字符串
,然后使用
SimpleDataFormat
将其解析为
date
对象,如下所示:

DataInputStream in = new DataInputStream(myFileInputStream);
BufferedReader  br = new BufferedReader(new InputStreamReader(in));
String strLine;

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
while ((strLine = br.readLine()) != null)
{
    ....Do things....
    Date myDateTime = (Date)formatter.parse(myDateString);
    ...Do things....
}

日期和时区的转换成本很高。如果可以假设日期/时间彼此相似,则可以在分钟更改时转换日期和小时/分钟(或仅在使用GMT时转换日期),并自行生成秒

这将每分钟调用一次
parse
。根据你的假设,你可以每小时或每天做一次

String pattern = "yyyy-MM-dd HH:mm";
SimpleDateFormat formatter = new SimpleDateFormat(pattern);
String lastTime = "";
long lastDate = 0;
while ((strLine = br.readLine()) != null) {
    String myDateString = strLine.split(", ")[0];
    if (!myDateString.startsWith(lastTime)) {
        lastTime = myDateString.substring(0, pattern.length());
        lastDate = formatter.parse(lastTime).getTime();
    }
    Date date = new Date(lastDate + Integer.parseInt(myDateString.substring(pattern.length() + 1).replace(":", "")));
}

我建议编写一个自定义解析器,这样会更快。比如:

Date parseYYYYMMDDHHMM(String strDate) {
   String yearString = strDate.substring(0, 4);
   int year = Integer.parseInt(yearString);
   ...
另一种方法是使用预先计算的datetime(w/o millis)到unix时间戳的哈希映射。如果没有太多不同的日期(或者,一旦日期翻转,您可以重新计算它)。

tl;博士
  • 使用java.time而不是遗留类
  • 使用
    DateTimeFormatter
    String
    解析为
    LocalDateTime
    ,每次所需时间小于1500纳秒(0.0000015秒)
java.time 您使用的是麻烦的旧日期时间类,它们现在是遗留的,被java.time类取代

让我们做一点微基准测试,看看java.time中解析日期时间字符串的速度有多慢

ISO 8601 ISO 8601标准定义了文本表示日期时间值的合理实用格式。默认情况下,java.time类在解析/生成字符串时使用这些标准格式

如问题所示,使用这些标准格式,而不是自己发明

DateTimeFormatter
定义与输入匹配的格式模式

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss:SSS" );
我们将把每个这样的输入解析为
LocalDateTime
,因为您的输入缺少时区或UTC偏移量的指示符。请记住,这些值并不代表一个时刻,也不是时间线上的一个点。要成为实际力矩,需要区域/偏移的上下文

String inputInitial = "2012-05-02 12:08:06:950" ;
LocalDateTime ldtInitial = LocalDateTime.parse( inputInitial , f );
让我们做一堆这样的输入

int count = 1_000_000;
List < String > inputs = new ArrayList <>( count );

for ( int i = 0 ; i < count ; i++ )
{
    String s = ldtInitial.plusSeconds( i ).format( f );
    inputs.add( s );
}
转储到控制台

System.out.println( "Parsing " + count + " strings to LocalDateTime took: " + d  + ". About " + nanosPerParse + " nanos each.");
将1000000个字符串解析为LocalDateTime需要:PT1.320778647S。每个大约1320纳米

太慢了? 因此,在一台配备四核Intel i7 CPU的MacBook Pro笔记本电脑上,解析一百万个这样的输入大约需要一秒半的时间。在我的测试运行中,每次解析大约需要1000到1500纳秒

在我看来,这不是性能问题


关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
java.sql.*

从哪里获得java.time类

  • ,及以后
    • 内置的
    • 标准JavaAPI的一部分,带有捆绑实现
    • Java9添加了一些次要功能和修复
    • 大部分java.time功能都在中向后移植到Java6和Java7
    • 更高版本的Android捆绑包实现了java.time类

    • 对于早期的Android(您是否尝试在整个文件解析操作中使用相同的SimpleDataFormat实例?您是如何确定其速度慢的?发布的代码不足以说明您是如何处理这种情况的。您的文件中有多少行,需要多长时间?请看SimpleDataFormat::parse(String)的代码)要知道这不是一件容易的任务。特别是错误处理是一件相当麻烦的事情。如果你的日期看起来总是一样的,你可以自己从行中解析它们并相应地填充日期实例。如果这样更快,我就不敢事先回答。我真的希望人们停止将DataInputStream与BufferedReader混合。哇我们可以假设文件是按日期/时间顺序的吗?到目前为止,这是最好的答案!!太棒了!!有趣的是,“LocalDateTime.parse(..).toEpochSecond(ZoneOffset.UTC)”实际上比使用相同模式(“yyyy-MM-dd'T'HH:MM:ss”)的“SimpleDateFormat#parse(..).getTime()慢.对我来说大约是10-15%我没想到。
      System.out.println( "Parsing " + count + " strings to LocalDateTime took: " + d  + ". About " + nanosPerParse + " nanos each.");