Можно ли использовать while ((line = r.readLine ())! = Null) construct? [закрыто]

Я хочу реорганизовать следующий код, потому что мне не комфортно использовать назначение внутри оператора сравнения. Это похоже на довольно идиоматический C, но вы думаете, что это хорошая практика в Java?

private void demoA (BufferedReader reader) бросает IOException {
    Строка = нуль;
    while ((line = reader.readLine ())! = null) {
        йоЗотеЬЫпд (линия);
    }
}

Вот альтернатива.

private void demoB (BufferedReader reader) бросает IOException {
    Строковая строка = reader.readLine ();
    while (строка! = null) {
        йоЗотеЬЫпд (линия);
        line = reader.readLine ();
    }
}

UPDATE: я наткнулся на аналогичный вопрос , заданный пару лет назад. Похоже, что мнения о том, хорошо ли это или нет, разделены. Тем не менее, Guava и Commons IO предоставляют альтернативные решения для этой проблемы. Если бы у меня была какая-либо из этих библиотек в текущем проекте, я бы, скорее всего, использовал их.

49 голосов | спросил mkalkov 12 MarpmWed, 12 Mar 2014 13:24:30 +04002014-03-12T13:24:30+04:0001 2014, 13:24:30

6 ответов


64

Присвоение внутри условия в этом случае в порядке, так как присваивание окружено дополнительной парой круглых скобок - сравнение, очевидно, ! = null, нет никаких шансов, что мы хотим type line == reader.readLine ().

Однако цикл для может быть здесь более изящным:

for (String line = reader.readLine (); line! = null; line = reader.readLine ()) {
    йоЗотеЬЫпд (линия);
}

В качестве альтернативы мы могли бы сделать это, что также ограничивает область line, как при использовании для -loop, и дополнительно исключает ненужное повторение:

while (true) {
    final Строка line = reader.readLine ();
    if (line == null) break;

    йоЗотеЬЫпд (линия);
}

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

ответил amon 12 MarpmWed, 12 Mar 2014 14:05:44 +04002014-03-12T14:05:44+04:0002 2014, 14:05:44
20

Вы можете немного увеличить уровень абстракции кода с помощью итераторного шаблона и в то же время вы можете повторно использовать существующую библиотеку (с опытом авторов): Apache Commons IO LineIterator . Он заменил бы нулевую проверку на немного читаемый hasNext () /nextLine ().

Использование итератора скрывает ненужную деталь: читатель возвращает null, когда данных больше нет. Метод hasNext () находится ближе к (английскому) языку, код легче читать. Вы все еще можете проверить детали внутри LineIterator, если вам это нужно, но обычно читатели /сопровождающие более счастливы с более высоким уровнем обзора метода, который легче понять. ( Этот ответ и вопрос содержат выразительный пример.)

Пример метода:

private void demoC (BufferedReader reader) бросает IOException {
    final LineIterator it = новый LineIterator (считыватель);
    пытаться {
        while (it.hasNext ()) {
            Строка line = it.nextLine ();
            //делаем что-то с линией
        }
    } в конце концов {
        it.close ();
    }
}

См. также: Эффективная Java, 2nd edition , Пункт 47: Знать и использовать библиотеки (Автор упоминает только встроенные библиотеки JDK, но я думаю, что рассуждения может быть правдой и для других библиотек.)

ответил palacsint 12 MarpmWed, 12 Mar 2014 15:28:26 +04002014-03-12T15:28:26+04:0003 2014, 15:28:26
13

Вместо того, чтобы обернуть читателя в итераторе, вы можете также обернуть его в Iterable, который затем вернет итератор.

Это позволит вам написать следующие

for (Строка: linesOf (reader)) {
     //...
}

, который делает очень чистый код.

ответил Cephalopod 13 MaramThu, 13 Mar 2014 00:36:49 +04002014-03-13T00:36:49+04:0012 2014, 00:36:49
5

По-моему, demoA () в порядке, как есть.

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

ответил 200_success 13 MaramThu, 13 Mar 2014 03:47:57 +04002014-03-13T03:47:57+04:0003 2014, 03:47:57
2

Пожалуйста, поймите, что

if (cond (var = expr))

обычно можно переписать как

var = expr;
if (cond (var)) ...

и

while (cond (var = expr))

может всегда переписываться как

for (var = expr; cond (var); var = expr)

, даже не затрагивая значение break; или continue; в цикле.

Таким образом, довольно редко возникает необходимость в назначении cramming в условия условных выражений.

ответил David 14 MarpmFri, 14 Mar 2014 13:50:35 +04002014-03-14T13:50:35+04:0001 2014, 13:50:35
1

Возможно, вы также можете сделать что-то подобное:

Files.lines (путь)

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

Этот ответ дает вам подход к функциональному программированию. Большая часть метода не требует пояснений.

Files.lines (Paths.get (путь)). map (- Ваша бизнес-логика--);

В паровом API доступны различные функции, которые облегчают вашу обработку.

ответил Joydeep Bhattacharya 29 AMpSun, 29 Apr 2018 08:11:56 +030011Sunday 2018, 08:11:56

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132