问题描述
- 我有一个生成
List<String>
的方法
- I have a method that produces a
List<String>
- see
java.nio.Files.readAllLines(Path)
- see
我的方法
我很想将List<String>
压成一个大的String
,但是我的常识是刺痛.所以在我盲目地做这样的事情之前:
My approach
I'm sorely tempted to just flatten that List<String>
into one big String
, but my common sense is tingling. So before I blindly did something like this:
List<String> fileLines = Files.readAllLines(Paths.get(""));
String jsonString = "";
for (String s : fileLines) {
jsonString += s;
}
JSONObject jsonObject = new JSONObject(jsonString);
我停下来思考,搜索和询问.我发现的一件事是NetBeans提出以下建议:
I stopped to think and search and ask. One thing I found was that NetBeans suggests the following:
List<String> fileLines = Files.readAllLines(Paths.get(""));
String jsonString = fileLines.stream().map((s) -> s)
.reduce(accountsJsonString, String::concat);
JSONObject jsonObject = new JSONObject(jsonString);
但是我妈妈总是警告我不要使用我不懂的代码.我认为这仍然是将所有数据复制并阻塞到一个大String中,所以我看不出它和我最初想到的有什么实际区别.
but my mother always warned me about using code I don't understand. I think this is still copying all the data and jamming it together into one big String, so I don't see any practical difference between that and what I originally came up with.
就最佳实践而言,仅将所有行粘贴到一个大字符串中是否有问题?有没有一种方法可以实现我的目标(使用java.nio
和org.json
)将冗长的JSON文件从磁盘读入内存,并且不需要在读取文件后立即复制文件内容?
Is there something wrong with simply gluing all the lines together into one big String, in terms of best practices? Is there a way to achieve my goal of (using java.nio
and org.json
in) reading a longish JSON file off disk and into memory that doesn't require duplicating the contents of the file once it's been read in?
问题的上半部分(概念上)的答案表明,发生的情况比我意识到的要糟.我结合了这些 两个一起回答,以解决我问题的后半部分(实际部分),如下所示:
This answer to the first (conceptual) half of my question shows there was worse going on than I realized. I've combined these two answers together to address the second (practical) half of my question as follows:
BufferedReader jsonReader = Files.newBufferedReader(Paths.get(...));
JSONObject jsonObject = new JSONObject(new JSONTokener(jsonReader));
推荐答案
简短的答案是您想更改读取文件的方式!
The short answer is that you want to change the way you're reading the file!
目前需要获取垃圾回收的String
对象的数量存在问题(请记住,String
是不可变的,因此每次添加一个对象时,它都会创建一个新对象)一点).列表的长度也具有二次运行时间,因为每次添加内容时,它都需要复制的String
越来越长.
The code you've got at the moment is problematic in terms of the number of dead String
objects that need garbage collecting (remember that a String
is immutable, so it's creating a new object each time you add a bit on). It's also got quadratic runtime in the length of the list, because each time it adds something on, it has a longer and longer String
that it needs to copy.
我认为NetBeans所建议的功能样式Java 8代码也将是二次方的:它将在函数中重复使用concat
.
I think that the functional-style Java 8 code that NetBeans is suggesting is also going to be quadratic: it's going to be using that concat
repeatedly in its reduce function.
您的另一个选择是使用StringBuffer
或char
数组.使用后者,您可以遍历列表以确定总长度,相应地分配一个数组,将内容放入数组中,然后从中创建一个大的String
.这将使您的总长度呈线性,而不是平方.
Your other option would be to use a StringBuffer
or an array of char
. With the latter, you can loop through the list determining total length, allocate an array accordingly, put things into the array, and then create a big String
from that. That will give you something linear in the total length, rather than quadratic.
这篇关于警惕扁平化长长的List< String>成字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!