在Java 8中的文件上泛化函数

在Java 8中的文件上泛化函数,java,java-8,nio,generalization,Java,Java 8,Nio,Generalization,我正在尝试使用JDK 8用Java编写一个Concordance程序(以重新学习该语言)。到目前为止,我有以下信息(包名省略): import java.io.IOException; 导入java.nio.file.Files; 导入java.nio.file.path; 导入java.util.HashMap; 导入java.util.Map; 公共班机{ 公共静态映射generateConcordance(字符串文件名)引发IOException{ 映射一致性=新的HashMap(); f

我正在尝试使用JDK 8用Java编写一个Concordance程序(以重新学习该语言)。到目前为止,我有以下信息(包名省略):

import java.io.IOException;
导入java.nio.file.Files;
导入java.nio.file.path;
导入java.util.HashMap;
导入java.util.Map;
公共班机{
公共静态映射generateConcordance(字符串文件名)引发IOException{
映射一致性=新的HashMap();
for(字符串行:Files.readAllLines(path.get(fileName))){
for(字符串字:line.split(“[\\p{Punct}\\s]+”){
合并(字,1,整数::和);
}
}
返回一致性;
}
公共静态void main(字符串[]args){
如果(args.length==0){
System.err.println(“无效操作-必须指定输入文件”);
}否则{
试一试{
映射一致性=生成一致性(args[0]);
concordance.forEach((键,值)->System.out.println(键+“\t”+值));
}捕获(IOException错误){
System.err.println(“I/O错误-无法读取文件:“+args[0]);
}
}
}
}

这是可行的,但我想对实现进行概括,使其能够在未传递任何参数的情况下从
系统中读取输入。是否可以修改函数
generateConcordance
的输入,以允许将其应用于命名文件或
系统。在
中?

进行一点重构,并使用
,这应该非常简单。您可以尝试以下方法(未经测试):

公共类主{
私有静态最终模式wordBreak=Pattern.compile(“[\\p{Punct}\\s]+”;
公共静态地图生成协调(流线){
回程线
.flatMap(wordBreak::splitAsStream)
.collect(Collectors.groupingBy(Function.identity()、Collectors.counting());
}
公共静态映射generateConcordance(字符串文件名)引发IOException{
try(streamlines=Files.lines(path.get(fileName))){
返回生成一致性(行);
}
}
公共静态映射生成一致性(InputStream in){
InputStreamReader reader=新的InputStreamReader(in,StandardCharsets.UTF_8);
返回generateConcordance(新的BufferedReader(reader).lines());
}
公共静态void main(字符串[]args){
尝试
{
generateConcordance(“SomeRandomFile.txt”);
发电协调(System.in);
}
捕获(IOE异常)
{
e、 printStackTrace(System.err);
}
}
}

为什么不在没有参数的情况下重载generateConcordance(),并为其提供System的默认行为。顺便说一句,关于Java中的可选参数:我希望我的实现尽可能容忍精化。如果我在
中读取用户指定的文件或系统,
generateConcordance
背后的算法不应该改变(这基本上类似于C中的
stdin
)。。。我不明白怎么回事,通常你会使用可选参数不?我想我不太明白你的建议。我基本上试图做的是看看我是否可以泛化外部for循环:
for(字符串行:Files.readAllLines(path.get(fileName))
System.in
fileName
上操作。阅读文档时,我看不到一种简单的方法。这正是我要做的。你也可以做
lines.flatMap(Pattern.compile([\\p{Punct}\\s]+”):splitAsStream).
只编译一次正则表达式。或者将编译后的模式存储在常量中,然后
lines.flatMap(wordBreak::splitAsStream).
最好关闭IO流。目前它们没有自动关闭。我认为您不想关闭
generateConcordance(…)
方法中的
InputStream
。在我看来,在调用者中这样做似乎更合乎逻辑,因为调用者在打开它的地方,可能使用try with resources作为所有权,以防调用者想要倒带
文件输入流(例如),并用它做其他事情。不幸的是,关闭包装器(
InputStreamReader
BufferedReader
)也会关闭底层流。@msandiford:我同意
generateConcordance(InputStream in)
,但它是在
映射generateConcordance(String fileName)
方法中创建和关闭的。见文件。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class Main {

    public static Map<String,Integer> generateConcordance(String fileName) throws IOException {
        Map<String,Integer> concordance = new HashMap<>();

        for (String line : Files.readAllLines(Paths.get(fileName))) {
            for (String word : line.split("[\\p{Punct}\\s]+")) {
                concordance.merge(word, 1, Integer::sum);
            }
        }

        return concordance;
    }

    public static void main(String[] args) {
        if (args.length == 0) {
            System.err.println("invalid operation - you must specify an input file");
        } else {
            try {
                Map<String, Integer> concordance = generateConcordance(args[0]);
                concordance.forEach((key,value) -> System.out.println(key + "\t" + value));
            } catch (IOException error) {
                System.err.println("I/O error - unable to read the file: " + args[0]);
            }
        }

    }

}
public class Main {

  private static final Pattern wordBreak = Pattern.compile("[\\p{Punct}\\s]+");

  public static Map<String, Long> generateConcordance(Stream<String> lines) {
    return lines
      .flatMap(wordBreak::splitAsStream)
      .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
  }

  public static Map<String, Long> generateConcordance(String fileName) throws IOException {
    try (Stream<String> lines = Files.lines(Paths.get(fileName))) {
      return generateConcordance(lines);
    }
  }

  public static Map<String, Long> generateConcordance(InputStream in) {
    InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
    return generateConcordance(new BufferedReader(reader).lines());
  }

  public static void main(String[] args) {
    try
    {
      generateConcordance("SomeRandomFile.txt");
      generateConcordance(System.in);
    }
    catch (IOException e)
    {
      e.printStackTrace(System.err);
    }
  }
}