为什么在Java中将字符串解析为日期很慢?我们能加速吗?
我正在读取一个包含日期的文本文件,我想在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 我逐行读取文件,然后从每行获取日期字符
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
,每次所需时间小于1500纳秒(0.0000015秒)LocalDateTime
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.");