在Android中格式化大量日期/时间对象的最快方法是什么?

时间:2013-10-17 16:54:40

标签: android performance

我正在寻找生成将在文本文件输出中使用的长日期/时间列表的最快方法。我想要实现的一个例子:

1,2013-10-17 00:00:00,数据,数据
2,2013-10-17 00:00:01,数据,数据
3,2013-10-17 00:00:02,数据,数据
....

这是我必须遵守的格式,不能更改。这些数据很容易达到100,000多行。我目前正在做的是:

//text_output is a printstream to SD card
logged_time = Calendar.getInstance();
dateFormat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
// these values are gathered from a device via bluetooth
logged_time.set(year, month, day, hour, minute, second);

while(I_still_have_lines_to_process){
    // print the line
    text_output.print(line_count + "," + dateFormat.format(logged_time.getTime()) + data etc.)
    // add the sample rate to calculate next date/time
    logged_time.add(Calendar.SECOND, sample_rate);
}

我发现对于250k行,此过程仅需50秒即可完成格式化。我还必须解析数据本身并通过蓝牙传输。如果我能提高速度,用户体验将大大提高。有更快的方法吗?

感谢阅读!

1 个答案:

答案 0 :(得分:3)

我将您的代码重写为我可以实际运行和测试的内容,最后使用下面的代码。这很粗糙,但对我有用,我将以此为基础。如果有些内容与您的实际行为不符,请仔细检查。

private static final int SAMPLE_RATE = 1;

public static void main(String[] args) {
    long time = System.currentTimeMillis();

    Calendar logged_time = Calendar.getInstance();
    Format dateFormat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");

    try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("out.txt"), StandardCharsets.UTF_8)) {
        for (int i = 0; i < 100000; i++) {
            // print the line
            writer.write(i + ", " + dateFormat.format(logged_time.getTime()));
            writer.newLine();

            // add the sample rate to calculate next date/time
            logged_time.add(Calendar.SECOND, SAMPLE_RATE);
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    System.out.println(System.currentTimeMillis() - time + " ms");
}

当我在我的机器上运行时,我平均得到1000毫秒。

简单地改变

dateFormat.format(logged_time.getTime())

dateFormat.format(logged_time)

平均导致730毫秒。您不需要每次都创建新的Date个对象。

但我们可以做得更好!重复工作有一个很多 - 我们不必每次都重复格式化整个日期。让我们缓存大部分格式化的日期,只检查我们是否必须在秒数溢出时重新格式化它:

private static final int SAMPLE_RATE = 1;

public static void main(String[] args) {
    long time = System.currentTimeMillis();

    Calendar logged_time = Calendar.getInstance();
    Format dateFormatNoSecs = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:");
    Format dateFormatSecs = FastDateFormat.getInstance("ss");

    String lastFormattedDateNoSecs = dateFormatNoSecs.format(logged_time);
    int lastSecs = logged_time.get(Calendar.SECOND);

    try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("out.txt"), StandardCharsets.UTF_8)) {
        for (int i = 0; i < 100000; i++) {
            int secs = logged_time.get(Calendar.SECOND);
            if (secs < lastSecs) {
                // at least minutes changed, we need to reformat it
                lastFormattedDateNoSecs = dateFormatNoSecs.format(logged_time);
            }
            // print the line
            writer.write(i + ", " + lastFormattedDateNoSecs + dateFormatSecs.format(logged_time));
            writer.newLine();

            // add the sample rate to calculate next date/time
            logged_time.add(Calendar.SECOND, SAMPLE_RATE);
            lastSecs = secs;
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    System.out.println(System.currentTimeMillis() - time + " ms");
}

610 ms。

最后的微观优化:一种自定义手动格式化器,只需几秒钟。奇怪的是,对于秒格式化,DecimalFormatFastDateFormat慢。但是一个简单的开关是最快的:

public class TwoDigitIntegerFormatter {

    public static String format(int number) {
        assert (number >= 0) && (number <= 99);

        switch (number) {
            case 0: return "00";
            case 1: return "01";
            case 2: return "02";
            case 3: return "03";
            case 4: return "04";
            case 5: return "05";
            case 6: return "06";
            case 7: return "07";
            case 8: return "08";
            case 9: return "09";
            default: return String.valueOf(number);
        }
    }

}

我们也可以手动维护第二个计数:

private static final int SAMPLE_RATE = 1;

public static void main(String[] args) {
    long time = System.currentTimeMillis();

    Calendar logged_time = Calendar.getInstance();
    Format dateFormatNoSecs = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:");

    String lastFormattedDateNoSecs = dateFormatNoSecs.format(logged_time);
    int secs = logged_time.get(Calendar.SECOND);

    try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("out.txt"), StandardCharsets.UTF_8)) {
        for (int i = 0; i < 100000; i++) {
            if (secs > 59) {
                // at least minutes changed, we need to reformat it
                lastFormattedDateNoSecs = dateFormatNoSecs.format(logged_time);
                secs %= 60;
            }
            writer.write(i + ", " + lastFormattedDateNoSecs + TwoDigitIntegerFormatter.format(secs));
            writer.newLine();

            // add the sample rate to calculate next date/time
            logged_time.add(Calendar.SECOND, SAMPLE_RATE);
            secs += SAMPLE_RATE;
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    System.out.println(System.currentTimeMillis() - time);
}

510毫秒。即使您的代码不完全相同,您也可以使用此解决方案中的想法来帮助自己。