У меня есть следующий код:
Stream<String> lines = reader.lines();
Если первая строка равна, "email"
я хочу удалить первую строку из потока. Для других строк из потока мне не нужна эта проверка.
Как я мог заболеть?
PS
Конечно, я могу преобразовать его в список, затем использовать old school for loop, но в дальнейшем мне снова нужен поток.
java
java-stream
java-11
gstackoverflow
источник
источник
skip(long n)
то, что пропускает первыеn
элементы, но я не знаю, можете ли вы как-то это обусловить ...stream.dropWhile(s -> s.equals("email"));
Ответы:
Хотя читатель будет в неопределенном состоянии после того, как вы построите из него поток строк, он будет в четко определенном состоянии, прежде чем вы это сделаете.
Так что вы можете сделать
Что является самым чистым решением на мой взгляд. Обратите внимание, что это не то же самое, что и в Java 9
dropWhile
, из-за которого было бы больше одной строки, если они совпадаютисточник
Если вы не можете получить список и должны делать это только с помощью a
Stream
, вы можете сделать это с помощью переменной.Дело в том, что вы можете использовать переменную только в том случае, если она является «окончательной» или «фактически конечной», поэтому вы не можете использовать буквальное логическое значение. Вы все еще можете сделать это с
AtomicBoolean
:Примечание: мне не нравится использовать «внешние переменные»,
Stream
потому что побочные эффекты - плохая практика в парадигме функционального программирования. Лучшие варианты приветствуются.источник
compareAndSet
очень элегантного способа установки и получения флага одновременно, приятно.stream.filter(!first.compareAndSet(true, false) || !s.equals("email"))
хоть и спорным.predicate
должны быть лицами без гражданстваAtomicBoolean
здесь используется для обслуживания параллельных потоков (какcompareAndSet
предполагает использование ), то это совершенно неправильно, так как это будет работать, только если поток является последовательным. Если вы используете технику,stream.sequential().filter(...)
однако, я согласен, что она будет работать.Чтобы не проверять условие в каждой строке файла, я просто прочитал и проверил первую строку отдельно, а затем запустил конвейер для остальных строк без проверки условия:
Проще на Java 9+:
источник
Stream.ofNullable(first).filter(not("email"::equals))
@ Arnouds ответ правильный. Вы можете создать один поток для первой строки, а затем сравнить, как показано ниже,
источник
limit(0)
конечно, должно бытьlimit(1)
....limit(0).filter(line -> !line.startsWith("email"))
не имеет смысла. Предикат никогда не будет оценен. Для источника потока, способного воспроизводить потоки, комбинацияlimit(1)
первого иskip(1)
второго будет правильной. Для потокового источника, такого как читатель, ни работать , ни работатьlimit(1)
неlimit(0)
будет. Вы только что изменили, какая линия безоговорочно проглатывается. Даже если вы нашли комбинацию, которая, как оказалось, выполняет желаемое действие, она будет основана на неуказанном, зависящем от реализации поведении.Чтобы отфильтровать элементы по их индексу, вы можете использовать
AtomicInteger
для хранения и увеличения индекса при обработкеStream
:Такой подход позволяет фильтровать элементы по любому индексу, а не только по первому.
источник
Чуть более запутанный, получая вдохновение из этого фрагмента .
Вы можете создать объект,
Stream<Integer>
который будет представлять индексы, и «сжать» его,Stream<String>
чтобы создатьStream<Pair<String, Integer>>
Затем отфильтруйте, используя индекс, и сопоставьте его с
Stream<String>
источник
Вот пример с
Collectors.reducing
. Но в конце концов создает список в любом случае.источник
Попробуй это:
источник