当前位置: 首页 > 面试题库 >

StringTokenizer-使用整数读取行

张嘉
2023-03-14
问题内容

我有一个关于代码优化的问题(可以运行,但是太慢了……)。我正在阅读形式的输入

X1 Y1
X2 Y2
etc

其中Xi,Yi是整数。我bufferedReader用于读取行,然后StringTokenizer用于处理这些数字,如下所示:

StringTokenizer st = new StringTokenizer(line, " ");

int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());

问题在于,这种方法在处理大型数据集时似乎效率低下。您能否建议我做一些简单的改进(我听说可以使用一些整数分析int或regex)来提高性能?谢谢你的提示

编辑:也许我判断错了,必须在代码的其他地方进行一些改进…


问题答案:

(更新的答案)

我可以说,无论您的程序速度出现什么问题,选择分词器都不是其中之一。最初运行每种方法以使初始化古怪均匀之后,我可以在毫秒内解析1000000行的“ 12
34”。如果愿意,可以改用indexOf,但我确实认为您需要查看瓶颈的其他代码,而不是这种微优化。拆分对我来说是一个惊喜-
与其他方法相比,它真的非常慢。我已经在Guava拆分测试中添加了它,它比String.split快,但比StringTokenizer慢。

  • 分割:371ms
  • IndexOf:48毫秒
  • StringTokenizer:92毫秒
  • Guava Splitter.split():108毫秒
  • CsvMapper构建一个csv文档并解析为POJOS:237ms(如果将这些行构建为一个文档则为175ms!)

即使在数百万行中,此处的差异也可以忽略不计。

现在我的博客上有这样的文章:http : //demeranville.com/battle-of-the-
tokenizers-delimited-text-parser-performance/

我运行的代码是:

import java.util.StringTokenizer;
import org.junit.Test;

public class TestSplitter {

private static final String line = "12 34";
private static final int RUNS = 1000000;//000000;

public final void testSplit() {
    long start = System.currentTimeMillis();
    for (int i=0;i<RUNS;i++){
        String[] st = line.split(" ");
        int x = Integer.parseInt(st[0]);
        int y = Integer.parseInt(st[1]);
    }
    System.out.println("Split: "+(System.currentTimeMillis() - start)+"ms");
}

public final void testIndexOf() {
    long start = System.currentTimeMillis();
    for (int i=0;i<RUNS;i++){
        int index = line.indexOf(' ');
        int x = Integer.parseInt(line.substring(0,index));
        int y = Integer.parseInt(line.substring(index+1));
    }       
    System.out.println("IndexOf: "+(System.currentTimeMillis() - start)+"ms");      
}

public final void testTokenizer() {
    long start = System.currentTimeMillis();
    for (int i=0;i<RUNS;i++){
        StringTokenizer st = new StringTokenizer(line, " ");
        int x = Integer.parseInt(st.nextToken());
        int y = Integer.parseInt(st.nextToken());
    }
    System.out.println("StringTokenizer: "+(System.currentTimeMillis() - start)+"ms");
}

@Test
public final void testAll() {
    this.testSplit();
    this.testIndexOf();
    this.testTokenizer();
    this.testSplit();
    this.testIndexOf();
    this.testTokenizer();
}

}

eta:这是番石榴代码:

public final void testGuavaSplit() {
    long start = System.currentTimeMillis();
    Splitter split = Splitter.on(" ");
    for (int i=0;i<RUNS;i++){
        Iterator<String> it = split.split(line).iterator();
        int x = Integer.parseInt(it.next());
        int y = Integer.parseInt(it.next());
    }
    System.out.println("GuavaSplit: "+(System.currentTimeMillis() - start)+"ms");
}

更新

我也添加了CsvMapper测试:

public static class CSV{
    public int x;
    public int y;
}

public final void testJacksonSplit() throws JsonProcessingException, IOException {
    CsvMapper mapper = new CsvMapper();
    CsvSchema schema = CsvSchema.builder().addColumn("x", ColumnType.NUMBER).addColumn("y", ColumnType.NUMBER).setColumnSeparator(' ').build();

    long start = System.currentTimeMillis();
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < RUNS; i++) {
        builder.append(line);
        builder.append('\n');
    }       
    String input = builder.toString();
    MappingIterator<CSV> it = mapper.reader(CSV.class).with(schema).readValues(input);
    while (it.hasNext()){
        CSV csv = it.next();
    }
    System.out.println("CsvMapperSplit: " + (System.currentTimeMillis() - start) + "ms");
}


 类似资料:
  • 问题内容: 因此,我在Go中构建了一个网络应用程序,我看到它读入了我创建时使用的有限字节数组,现在的 问题 是我不知道内容的确切长度,因此它可能是太多或不足。 我的问题是我如何才能读取准确的数据量。我认为我必须使用,但不确定。 问题答案: 这在很大程度上取决于您要执行的操作以及所期望的数据类型,例如,如果您只想读到EOF,则可以使用以下内容: // edit:出于完整性考虑,@ fabrizioM

  • 爪哇岛。所以我想输入一个整数数组,然后使用 StringTokenizer 打印出最大值。我知道如何使用整数来做到这一点,但是当我尝试使用数组时,字符串到 int 命令 (Integer.parseInt) 失败了 - 无法从 int 转换为 int[]。 我该如何解决这个问题,或者我应该使用其他命令吗?

  • 我在开始一个分配给我的项目时遇到了一点困难。我不能使用字符串运算符、等。我需要将文件扫描到EOF。 以下是该文件的一个示例: 我试图做的是设置一个while循环: 然后尝试检查cur_gate字符串是什么: 问题是,我不知道读完字符串后我将如何扫描3个整数。然后最终,一旦它读取特殊,我需要扫描4个整数。 我想将第一个整数存储在一个名为输出的数组中,其余的存储在一个名为输入的数组中。 总之,我应该如

  • 如何从ReactJS组件中获取完整的URL? 我认为它应该是这样的东西,但它是

  • 我希望你帮助我理解我应该如何做以下事情: 我有一个包含由空格“”分隔的整数的文件。我需要读取所有整数,对它们进行排序,并将它们作为字符串写入另一个文件。我写了一个代码,但是我一个字符一个字符地读,把这个单词放在一个字符子数组[Max_Int]中,当我遇到“”时,我把这些字符,现在是一个字符串,在原子化后放到另一个主Int数组中,直到到达文件的末尾,一个字符串接一个字符串,然后我对它们进行排序并将它