我有什么:我有一个逐行读取的文件。这些行不计入文件中。
我想做什么:我想计算一个流中的每一行,只返回发生某个文本的数字。
到目前为止我有什么:
public static Integer findLineNums(String word)
throws IOException {
final Map<String, Integer> map = new HashMap<>();
final List<String> lines = Files.lines(Paths.get(PATH)).collect(Collectors.toList());
IntStream.rangeClosed(0, lines.size()-1).forEach(f -> map.put(lines.get(f), f+1));
return map.get(word);
}
问题:如何仅使用SINGLE流来执行此操作?
编辑问题:我想在Stream中做所有事情,这也包括累积到列表中。
最佳案例场景如下:
Files.lines(Paths.get(PATH)).superAwesomeStreamFuncs().collect(Collectors.toList());
编辑:在我的情况下,我只返回一个整数,但我希望得到类似整数列表的东西。
答案 0 :(得分:2)
以下代码段会创建一个List<Integer>
,其中的行包含单词
String word = "foo";
List<Integer> matchedLines = new ArrayList<>();
final List<String> lines = Files.readAllLines(Paths.get("word_list.txt"));
IntStream.rangeClosed(0, lines.size() - 1).forEach(f -> {
if (lines.get(f).contains(word)) {
matchedLines.add(++f);
}
});
System.out.println("matchedLines = " + matchedLines);
假设文件word_list.txt
为
foo
bar
baz
foobar
barfoo
输出
matchedLines = [1, 4, 5]
修改要使用单个流解决此问题,请创建自定义Consumer
public class MatchingLines {
static class MatchConsumer implements Consumer<String> {
private int count = 0;
private final List<Integer> matchedLines = new ArrayList<>();
private final String word;
MatchConsumer(String word) {
this.word = word;
}
@Override
public void accept(String line) {
count++;
if (line.contains(this.word)) {
matchedLines.add(count);
}
}
public List<Integer> getResult() {
return matchedLines;
}
}
public static void main(String[] args) throws IOException {
MatchConsumer matchConsumer = new MatchConsumer("foo");
Files.lines(Paths.get("word_list.txt")).forEach(matchConsumer);
System.out.println("matchedLines = " + matchConsumer.getResult());
}
}
答案 1 :(得分:2)
这有效:
int[] i = new int[]{0}; // trick to make it final
List<Integer> hits = <your stream>
.map(s -> s.contains(word) ? ++i[0] : - ++i[0])
.filter(n -> n > 0)
.collect(Collectors.toList());
这里的主要“技巧”是使用数组,其引用不会改变(即它是“有效的最终”,但它允许我们改变它的(仅)元素作为计数器,无论如何都以内联方式递增。快速过滤器会抛出不匹配。
一些测试代码:
String word = "foo";
int[] i = new int[]{0};
List<Integer> hits = Stream.of("foo", "bar", "foobar")
.map(s -> s.contains(word) ? ++i[0] : - ++i[0])
.filter(n -> n > 0)
.collect(Collectors.toList());
System.out.println(hits);
输出:
[1, 3]
答案 2 :(得分:0)
此方法返回由文件中的数字映射的行。
public static Map<String, Integer> findLineNums(Path path, String word) throws IOException {
final Map<String, Integer> map = new HashMap<>();
int lineNumber = 0;
Pattern pattern = Pattern.compile("\\b" + word + "\\b");
try (BufferedReader reader = Files.newBufferedReader(path)) {
String line = null;
while ((line = reader.readLine()) != null) {
lineNumber++;
if (pattern.matcher(line).find()) {
map.put(line, lineNumber);
}
}
}
for (String line : map.keySet()) {
Integer lineIndex = map.get(line);
System.out.printf("%d %s\n", lineIndex, line);
}
return map;
}
BufferedReader
和Files.lines
流一样逐行读取文件。