Eu tenho o seguinte código:
Stream<String> lines = reader.lines();
Se a primeira corda for igual "email"
, quero remover a primeira do fluxo. Para outras seqüências de caracteres do fluxo, não preciso dessa verificação.
Como eu consegui isso?
PS
Claro que posso transformá-lo na lista e, em seguida, usar o loop for old school, mas ainda preciso transmitir novamente.
java
java-stream
java-11
gstackoverflow
fonte
fonte
skip(long n)
que ignora os primeirosn
elementos, mas eu não sei se você pode condicioná-lo de alguma forma ...stream.dropWhile(s -> s.equals("email"));
Respostas:
Embora o leitor esteja em um estado não especificado depois que você construiu um fluxo de linhas a partir dele, ele está em um estado bem definido antes de você fazer isso.
Então você pode fazer
Qual é a solução mais limpa na minha opinião. Observe que isso não é o mesmo que o Java 9
dropWhile
, que eliminaria mais de uma linha se corresponderem.fonte
Se você não pode ter a lista e deve fazê-lo apenas com a
Stream
, pode fazê-lo com uma variável.O problema é que você só pode usar uma variável se for "final" ou "efetivamente final", para que você não possa usar um booleano literal. Você ainda pode fazer isso com um
AtomicBoolean
:Nota: Não gosto de usar "variáveis externas"
Stream
porque os efeitos colaterais são uma má prática no paradigma de programação funcional. Melhores opções são bem-vindas.fonte
compareAndSet
é uma maneira muito elegante de definir e receber a bandeira ao mesmo tempo, legal.stream.filter(!first.compareAndSet(true, false) || !s.equals("email"))
embora discutível.predicate
deve ser apátridaAtomicBoolean
aqui for para atender fluxos paralelos (comocompareAndSet
sugere o uso de ), isso estará completamente errado, pois só funcionará se o fluxo for seqüencial. Se você usar a técnica nostream.sequential().filter(...)
entanto, eu concordo que funcionará.Para evitar verificar a condição em cada linha do arquivo, basta ler e verificar a primeira linha separadamente e, em seguida, executar o pipeline no restante das linhas sem verificar a condição:
Mais simples em Java 9+:
fonte
Stream.ofNullable(first).filter(not("email"::equals))
A resposta do @Arnouds está correta. Você pode criar um fluxo para a primeira linha e comparar como abaixo,
fonte
limit(0)
certamente deve serlimit(1)
....limit(0).filter(line -> !line.startsWith("email"))
não faz sentido. O predicado nunca será avaliado. Para uma fonte de fluxo capaz de reproduzir fluxos, a combinação delimit(1)
no primeiro eskip(1)
no segundo estaria correta. Para uma fonte de fluxo como um leitor,limit(1)
nemlimit(0)
funcionará. Você acabou de alterar qual linha é engolida incondicionalmente. Mesmo se você encontrar uma combinação que faz a coisa desejada, ela seria baseada no comportamento não especificado e dependente da implementação.Para filtrar elementos com base em seu índice, você pode usar
AtomicInteger
para armazenar e incrementar o índice ao processar umStream
:Essa abordagem permite filtrar elementos em qualquer índice, não apenas no primeiro.
fonte
Um pouco mais complicado, obtendo alguma inspiração deste trecho .
Você pode criar um
Stream<Integer>
que represente índices e "compactá-lo" com o seuStream<String>
para criar umStream<Pair<String, Integer>>
Em seguida, filtre usando o índice e mapeie-o de volta para um
Stream<String>
fonte
Aqui está um exemplo com
Collectors.reducing
. Mas no final cria uma lista de qualquer maneira.fonte
Tente o seguinte:
fonte