我只是偶然发现一个错误,问自己是否有更好的方法来做。
首先我有这段代码。
// read lines out of a file and do something with it in foo
BufferedReader br = new BufferedReader (new FileReader ("bla.txt"));
String line;
while ((line = br.readLine ()) != null)
{
foo (line);
}
br.close ();
然后我更改了它。引入了一个列表,而不是在读取循环中工作。
BufferedReader br = new BufferedReader (new FileReader ("bla.txt"));
List <String> lst = new ArrayList <String> ();
String line;
while ((line = br.readLine ()) != null)
{
lst.add (line);
}
br.close ();
for (String s : lst)
{
foo (line); // !!!
}
请忽略以下事实:这不是真正的优化。该代码只是我的问题的简化。
在使用收藏集时,我犯了一个错误。我确实将foo(line)替换为foo(s)。 那不是编译器错误,但是我的算法是错误的。
如果不更模块化(使用功能等),避免这种问题的一个好策略是什么?
我想通过将其放在一个块中来限制行的范围。
BufferedReader br = new BufferedReader (new FileReader ("bla.txt"));
List <String> lst = new ArrayList <String> ();
{
String line;
while ((line = br.readLine ()) != null)
{
lst.add (line);
}
br.close ();
}
for (String s : lst)
{
foo (line); // error now
}
但是我不确定这是一个通用且好的策略。对这种问题有什么建议吗?谢谢!
答案 0 :(得分:4)
您要寻找的是具有纯函数[1]。为了实现这一点,您应该具有两个单独的功能,一个用于读取内容,另一个用于处理内容。第二个函数应将参数作为列表。如下所示:
List<String> readContent(){
BufferedReader br = new BufferedReader (new FileReader ("bla.txt"));
List <String> lst = new ArrayList <String> ();
{
String line;
while ((line = br.readLine ()) != null)
{
lst.add (line);
}
br.close ();
}
return lst;
}
void processContent(List<String> contentList){
for (String s : contentList){
foo (s); // error now
}
}
在您的main方法中,您将调用以下两个函数:
List<String> contents = readContent();
processContent(contents);
此外,这两个功能也都应该进行单元测试。
答案 1 :(得分:2)
这只是一个建议,它仅在使用资源时有效,但对于您而言,您可以
br.close()
和line
-with-resource方法来限制声明try
的范围。看看下面的代码:
public static void main(String[] args) {
List <String> lst = new ArrayList <String> ();
// specifically try the BufferedReader, it will get closed in every case
try (BufferedReader br = new BufferedReader(new FileReader("bla.txt"))) {
String line;
while ((line = br.readLine()) != null) {
lst.add(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
lst.forEach(s -> System.out.println(s)); // Java 8 for-each
}
根据建议,我忽略了您的问题并不需要真正优化的事实。
答案 2 :(得分:1)
目前尚不清楚是否要在填充列表之后访问line变量,但是如果不想,则可以将其完全删除。
List<String> lst = new ArrayList<>(Files.readAllLines(Paths.get("bla.txt")));
for (String s : lst) {
foo(line); // error now
}
答案 3 :(得分:1)
另一个针对示例代码的解决方案:您可以在for循环的初始化语句中声明变量,该变量只能在循环的主体中访问。
for (String line=br.readLine(); line != null ; line = br.readLine()) {
//line is accessible
}
// line is undeclared
每个while
循环都可以转换为for
循环,但是产生的循环通常可能令人困惑,因此请多加注释。