警惕将longish List <string>展平为String </string>

时间:2014-08-29 21:10:55

标签: java json nio

我的情况

  1. 我有一个产生List<String>的方法
  2. 我有一个不同的方法需要String
  3. 我想从(1)获取输出并将其放入(2)
  4. 我的方法

    我非常想把List<String>变成一个大String,但我的常识是刺痛。所以在我盲目地做这样的事情之前:

    List<String> fileLines = Files.readAllLines(Paths.get(""));
    String jsonString = "";
    for (String s : fileLines) {
        jsonString += s;
    }
    JSONObject jsonObject = new JSONObject(jsonString);
    

    我停下来思考,搜索并问。我发现的一件事是NetBeans建议如下:

    List<String> fileLines = Files.readAllLines(Paths.get(""));
    String jsonString = fileLines.stream().map((s) -> s)
            .reduce(accountsJsonString, String::concat);
    JSONObject jsonObject = new JSONObject(jsonString);
    

    但我妈妈总是警告我使用我不理解的代码。我认为这仍然是在复制所有数据并将它们捆绑成一个大字符串,所以我看不出它和我最初想出的任何实际区别。

    我的问题

    在最佳实践方面,简单地将所有线条粘合成一个大字符串是否有问题?有没有办法实现我的目标(使用java.nioorg.json)从磁盘读取冗长的JSON文件,并进入内存,一旦读入文件内容不需要复制文件的内容?

    我使用的解决方案

    This answer对我问题的第一个(概念性的)一半表明,比我意识到的还要糟糕。我已将these two个答案合并在一起,以解决我问题的第二个(实际)问题,如下所示:

    BufferedReader jsonReader = Files.newBufferedReader(Paths.get(...));
    JSONObject jsonObject = new JSONObject(new JSONTokener(jsonReader));
    

4 个答案:

答案 0 :(得分:3)

为什么不使用设计用于将JSONObject加载到内存中的方法,而不是使用这些方法来构造JSONObject(看起来这是你的最终目标)。

Reader fromFile = new BufferedReader(new FileReader(myFile));
JSONTokener tokens = new JSONTokener(fromFile);
JSONObject myObject = new JSONObject(tokens);
fromFile.close();

然后你得到了你选择为你工作的JSON库:)

这取决于您指定的同一个库中的JSONTokener

答案 1 :(得分:2)

为什么不使用readAllBytes呢?在我看来,没有必要使用单独的行。

byte[] bytes = Files.readAllBytes(path);
String jsonString = new String(bytes, StandardCharsets.UTF_8);

但请注意该方法的警告:

  

请注意,此方法适用于将所有字节读入字节数组的简单方法。它不适合读取大文件。

因此,如果您使用的是大型文件,则应该使用BufferedReader

BufferedReader reader = Files.newBufferedReader(path);

答案 2 :(得分:1)

嗯,对我来说,这是一个更好的方法:

StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
for(String line : Files.readAllLines(Paths.get(""))) {
    pw.println(line);
}
String bigString = sw.toString();

这可以捕获换行符等。

答案 3 :(得分:1)

简短的回答是,您想要改变阅读文件的方式!

目前您获得的代码在需要垃圾收集的死String个对象的数量方面存在问题(请记住String是不可变的,因此它每个都创建一个新对象你添加一点的时间)。它在列表的长度上也有二次运行时,因为每次添加内容时,它都需要复制更长和更长的String

我认为NetBeans建议的函数式Java 8代码也将是二次的:它将在其reduce函数中重复使用concat

您的另一个选择是使用StringBufferchar数组。使用后者,您可以遍历列表确定总长度,相应地分配数组,将数据放入数组,然后从中创建一个大String。这将给你一些线性的总长度,而不是二次方。