I would write it as an Iterator
.
Get a Stream<String>
, ask for its Iterator
; then create a method that takes an Iterator<String>
and returns a Iterator<LogEvent>
.
Then turn that back into a Stream<LogEvent>
.
Lets assume, for now, that LogEvent
has something like this:
class LogEvent {
static Builder builder() {
return new Builder();
}
static class Builder {
Builder appendLine(final String line) {
//do stuff
return this;
}
LogEvent build() {
//validate?
return new LogEvent();
}
}
}
Then something like this would work:
Iterator<LogEvent> toLogEvents(final Iterator<String> lineIterator) {
return new Iterator<LogEvent>() {
@Override
public boolean hasNext() {
return lineIterator.hasNext();
}
@Override
public LogEvent next() {
final LogEvent.Builder builder = LogEvent.builder();
String line;
while(lineIterator.hasNext() && !(line = lineIterator.next()).isEmpty()) {
builder.appendLine(line);
}
return builder.build();
}
};
}
Now you can write a method:
Stream<LogEvent> toLogEvents(final Supplier<Stream<String>> fileReader) {
final Stream<String> lines = fileReader.get();
final Iterator<LogEvent> logEventIterator = toLogEvents(lines.iterator());
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(logEventIterator, Spliterator.ORDERED), false).onClose(() -> lines.close());
}