0

我在第 26 和 27 行有一个问题:

String dumb = input.nextLine();
output.println(dumb.replaceAll(REMOVE, ADD));

我希望我能够将其缩小到一行并能够节省空间,所以我做到了:

output.println(new String(input.nextLine()).replaceAll(REMOVE, ADD));

但现在我想知道性能。我知道这个程序很安静,不需要优化,但我想学习这个。
我看它的方式,在第一个场景中,我正在创建一个哑字符串对象,但是一旦我离开循环,对象就会被放弃,JVM 应该清理它,对吗?但是 JVM 清理废弃对象的速度是否比程序执行循环的速度更快?还是程序完成后会有几个字符串对象等待垃圾回收?

我的逻辑是否正确,在第二种情况下,String对象是动态创建的,一旦程序通过那条线就被销毁?这实际上是性能提升吗?

如果你能帮我解决这个问题,我将不胜感激。

谢谢你,

ps 如果您想知道程序(我假设它是直截了当的)它接收输入文件、输出文件和两个单词,程序获取输入文件,用第二个单词替换第一个单词并将其写入第二个文件。如果您实际上已经阅读了这篇文章,并且想提出一些可以让我的代码变得更好的方法,请这样做。我将不胜感激。

import java.io.File;
import java.util.Scanner;
import java.io.PrintWriter;

public class RW {

    public static void main(String[] args) throws Exception{
        String INPUT_FILE = args[0];
        String OUTPUT_FILE = args[1];
        String REMOVE = args[2];
        String ADD = args[3];

        File ifile = new File(INPUT_FILE);
        File ofile = new File(OUTPUT_FILE);

        if (ifile.exists() == false) {
            System.out.println("the input file does not exists in the current folder");
            System.out.println("please provide the input file");
            System.exit(0);
        }

        Scanner input = new Scanner(ifile);
        PrintWriter output = new PrintWriter(ofile);

        while(input.hasNextLine()) {
            String dumb = input.nextLine();
            output.println(dumb.replaceAll(REMOVE, ADD));
        }
        input.close();
        output.close();


    }
}
4

3 回答 3

3

我要说的第一件事是:

不要担心过早地优化性能。Java 编译器很聪明,它会为你优化很多这些东西,即使没有优化,你也只需要极少时间。你去那里的流 IO 已经运行了比你所说的时间长几个数量级的时间。

重要的是代码易于理解。你有一个很好的代码风格,从你的例子开始,所以坚持下去。这两个代码片段中的哪一个更容易被您以外的人阅读?是最好的选择。:)

也就是说,以下是对您的问题的一些更具体的答案:

  1. 垃圾收集绝对会拾取在循环范围内实例化的对象。它在循环内实例化的事实意味着,一旦它超出范围,Java 就已经将其标记为清理。下次 GC 运行时,它会清理所有标记为清理的东西。

  2. 内联创建对象仍将创建一个对象。构造函数仍然被调用,内存仍然被分配......在引擎盖下,它们真的非常相似。只是在一种情况下该对象具有名称,而在另一种情况下则没有。通过将两行代码合二为一,您不会节省任何实际资源。

  3. “input.nextLine()” 已经返回了一个字符串,所以你不需要将它包装在一个新的 String() 中。(所以是的,删除它实际上导致实例化的对象减少!)

于 2012-05-16T05:29:31.467 回答
1

一旦超出范围,本地对象就有资格进行 GC。这并不意味着 GC 会立即清理它们。符合条件的对象经历了一个生命周期。GC 可能会也可能不会立即收集它们。

就您的程序而言,除了一两行之外,没有什么可以优化的。下面是一个重组的程序。

import java.io.File;
import java.util.Scanner;
import java.io.PrintWriter;

public class Test {
    public static void main(String[] args) throws Exception {
        String INPUT_FILE = args[0];
        String OUTPUT_FILE = args[1];
        String REMOVE = args[2];
        String ADD = args[3];

        File ifile = new File(INPUT_FILE);
        File ofile = new File(OUTPUT_FILE);
        if (ifile.exists() == false) {
            System.out.println("the input file does not exists in the current folder\nplease provide the input file"); 
            System.exit(0);
        }
        Scanner input = null;
        PrintWriter output = null;
        try {
            input = new Scanner(ifile);
            output = new PrintWriter(ofile);
            while (input.hasNextLine()) {
                output.println(input.nextLine().replaceAll(REMOVE, ADD));
            }
        } finally {
            if (input != null)
                input.close();
            if(output != null)
                output.close();
        }
    }
}
于 2012-05-16T05:27:40.830 回答
1

如果您担心对象的创建和性能,请使用分析器来测量您的代码。请记住,这样做new String(input.nextLine())是完全没有意义的,因为它会input.nextLine()返回一个不可变的 String 实例。所以就做吧output.println(input.nextLine().replaceAll(REMOVE, ADD));

于 2012-05-16T05:40:31.727 回答