Nếu bạn muốn giữ bản chất lười biếng hiệu quả của Stream
s (tức là không đọc toàn bộ tệp nếu bạn chỉ muốn tìm kết quả đầu tiên), bạn sẽ phải tự xây dựng luồng. Đây không phải là quá khó, trở ngại duy nhất là sự vắng mặt của một loại tuple để thực hiện cả hai, một số dòng và một dòng String
. Bạn có thể, lạm dụng Map.Entry
trường hoặc tạo một loại chuyên dụng:
static final class NumberedLine {
final int number;
final String line;
NumberedLine(int number, String line) {
this.number = number;
this.line = line;
}
public int getNumber() {
return number;
}
public String getLine() {
return line;
}
@Override
public String toString() {
return number+":\t"+line;
}
}
sau đó bạn có thể thực hiện một dòng thẳng về phía trước:
public static Stream<NumberedLine> lines(Path p) throws IOException {
BufferedReader b=Files.newBufferedReader(p);
Spliterator<NumberedLine> sp=new Spliterators.AbstractSpliterator<NumberedLine>(
Long.MAX_VALUE, Spliterator.ORDERED|Spliterator.NONNULL) {
int line;
public boolean tryAdvance(Consumer<? super NumberedLine> action) {
String s;
try { s=b.readLine(); }
catch(IOException e){ throw new UncheckedIOException(e); }
if(s==null) return false;
action.accept(new NumberedLine(++line, s));
return true;
}
};
return StreamSupport.stream(sp, false).onClose(()->{
try { b.close(); } catch(IOException e){ throw new UncheckedIOException(e); }});
}
sử dụng phương pháp bạn có thể tìm kiếm sự xuất hiện đầu tiên
OptionalInt lNo=lines(path).filter(nl->nl.getLine().contains(word))
.mapToInt(NumberedLine::getNumber)
.findFirst();
hoặc thu thập tất cả chúng
List<Integer> all=lines(path).filter(nl->nl.getLine().contains(word))
.map(NumberedLine::getNumber)
.collect(Collectors.toList());
Hoặc, cũng trong mã sản xuất bạn muốn đảm bảo đóng cửa thích hợp các nguồn lực cơ bản:
OptionalInt lNo;
try(Stream<NumberedLine> s=lines(path)) {
lNo=s.filter(nl->nl.getLine().contains(word))
.mapToInt(NumberedLine::getNumber)
.findFirst();
}
resp.
List<Integer> all;
try(Stream<NumberedLine> s = lines(path)) {
all = s.filter(nl->nl.getLine().contains(word))
.map(NumberedLine::getNumber)
.collect(Collectors.toList());
}
kiểu trả về là một danh sách –
wundidajah