有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java生成所有可能的6长度字符串并写入文件的最快方法是什么?

我想生成所有可能的6长度字符串 我需要这种格式: aaa000 aaa001 ...

这是我的代码:

private List<String> licensePlateList = new ArrayList<>();
private List<String> numberList = new ArrayList<>();
private List<String> letterList = new ArrayList<>();

public static void main(String[] args) {
    Main app = new Main();
    long start = System.nanoTime();

    app.generateNumbers();
    int letters = 26;
    int count = 3;
    final int combinations = (int) Math.pow(letters, count);
    StringBuilder sb = new StringBuilder(count);
    for (int i = 0; i < combinations; i++) {
        sb.setLength(0);
        for (int j = 0, i2 = i; j < count; j++, i2 /= letters)
            sb.insert(0, (char) ('a' + i2 % letters));
        app.letterList.add(sb.toString());
    }

    long time = System.nanoTime() - start;
    System.out.printf("Took %.3f seconds to generate", time / 1e9);

    for (int i=0;i<app.letterList.size();i++){
        for (int j=0;j<app.numberList.size();j++){
            String licensePlate = app.letterList.get(i)+app.numberList.get(j);
            try(FileWriter fw = new FileWriter("licensePlate2.txt", true);
                BufferedWriter bw = new BufferedWriter(fw);
                PrintWriter out = new PrintWriter(bw))
            {
                out.println(licensePlate);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    time = System.nanoTime() - start;
    System.out.printf("Took %.3f seconds to generate %,d combinations%n", time / 1e9, app.licensePlateList.size());
}

private void generateNumbers(){
    for (int i=0;i<1000;i++){
        numberList.add(String.format("%03d", i));
    }
}
}

我在generateNumbers()方法中生成所有可能的数字。在main()方法中,在生成数字之后,我将所有可能的3长度字符串生成到letterList中。 在我用数字映射每个字符串并写入文件之后

但它真的很慢。你知道更快的方法吗


共 (2) 个答案

  1. # 1 楼答案

    $ java Test c:/temp/testOutput
    Generated 17576000 combinations in 1.456 seconds
    

    以下是代码:

    import java.io.*;
    
    public class Test {
    
        public static void main(String[] args) throws Exception {
            char sb[] = new char[7];
            sb[6] = '\n';
    
            int count = 0;
            long startTime = System.currentTimeMillis();
    
            BufferedWriter out = new BufferedWriter(new FileWriter(args[0]));
    
            for (char a = 'a'; a <= 'z'; a++) {
                sb[0] = a;
                for (char b = 'a'; b <= 'z'; b++) {
                    sb[1] = b;
                    for (char c = 'a'; c <= 'z'; c++) {
                        sb[2] = c;
                        for (char d = '0'; d <= '9'; d++) {
                            sb[3] = d;
                            for (char e = '0'; e <= '9'; e++) {
                                sb[4] = e;
                                for (char f = '0'; f <= '9'; f++) {
                                    sb[5] = f;
                                    out.write(sb);
                                    count++;
                                }
                            }
                        }
                    }
                }
            }
            out.close();
            long endTime = System.currentTimeMillis();
            System.err.println("Generated " + count + " combinations in " + (endTime - startTime) / 1000.0 + " seconds");
        }
    }
    

    请注意,在Linux上使用/dev/null运行相同的代码,在Windows上使用NUL产生的时间基本相同(减少0.2秒),因此磁盘IO成本几乎已摊销。每种组合的成本归结为1.456/17576000=0.082微秒。我相信C++可以做得更好。p>

    更新:将BufferedWriter更改为BufferedOutputStream,并将char[]替换为byte[]将时间缩短到.908秒。这是因为编写代码不再需要将Java的UTF-16编码转换为实际文件中使用的UTF-8

  2. # 2 楼答案

    你的算法是为每个车牌打开一个新的书写器

    相反,打开一个作家,把他们都写下来:

    try(FileWriter fw = new FileWriter("licensePlate2.txt", true);
        BufferedWriter bw = new BufferedWriter(fw);
        PrintWriter out = new PrintWriter(bw)) {
        for (String letters : app.letterList) {
            for (String numbers : app.numberList) {
                out.print(letters);
                out.println(numbers);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    请注意,此代码如何通过分别写入每个字符串来避免为整个许可证编号创建中间字符串

    还要注意“for each”循环的使用