Опасайтесь сглаживания длинного списка <String> в String

Моя ситуация

Мой подход

У меня очень соблазн просто сгладить этот 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.nio и org.json in), считывая длинный файл JSON с диска и в память, которая не требует дублирования содержимого файла после его чтения?

Решение, которое я использовал

Этот ответ на первую (концептуальную) половину моего вопроса показывает, что было хуже, чем я понял. Я объединил эти два, чтобы ответить на вторую (практическую) половину моего вопроса следующим образом:

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

Ответы

Ответ 1

Короткий ответ заключается в том, что вы хотите изменить способ чтения файла!

Код, который у вас есть на данный момент, проблематичен с точки зрения количества мертвых объектов String, которые требуют сбора мусора (помните, что a String является неизменным, поэтому он создает новый объект каждый раз, когда вы добавляете бит). Он также получил квадратное время выполнения в длине списка, потому что каждый раз, когда он добавляет что-то, он имеет более длинный и длинный String, который он должен скопировать.

Я думаю, что функциональный стиль кода Java 8, который предлагает NetBeans, также будет квадратичным: он будет использовать этот concat несколько раз в своей функции сокращения.

Другой вариант - использовать StringBuffer или массив char. С последним вы можете прокручивать список, определяющий общую длину, соответственно распределить массив, поместить вещи в массив и затем создать из него большой String. Это даст вам нечто линейное по всей длине, а не квадратичное.

Ответ 2

Вместо использования этих методов для создания JSONObject (кажется, что это ваша конечная цель), почему бы не использовать методы, предназначенные для загрузки JSONObject в память.

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

Затем вы получаете библиотеку JSON, которую вы выбрали для выполнения этой работы:)

Это зависит от JSONTokener из той же самой библиотеки, которую вы указали.

Ответ 3

Почему бы не использовать readAllBytes вместо этого? Мне кажется, что нет необходимости работать с отдельными линиями.

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

Однако обратите внимание на предупреждение по этому методу:

Обратите внимание, что этот метод предназначен для простых случаев, когда удобно считывать все байты в массив байтов. Он не предназначен для чтения в больших файлах.

Итак, если вы работаете с большим файлом, вы, вероятно, должны использовать BufferedReader:

BufferedReader reader = Files.newBufferedReader(path);

Ответ 4

Хорошо, для меня это лучший способ сделать это:

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

Это захватывает разрывы строк и т.д.