我正在尝试将for循环转换为基于java-8 forEach的语句。当循环在数组中遇到'\n‘字符并返回数组中该位置的索引时,循环就会中断。
protected Integer skipLine(byte[] buf,Integer len, Integer i) {
for(;i<len;i++) {
if(buf[i] == '\n') {
newLine();
return ++i;
}
}
return i;
}相当于Java-8:
protected Integer skipLine(byte[] buf,Integer len, Integer i) {
IntStream stream = IntStream.range(i, len).map(j -> buf[j]); // this is necessary because there's no ByteStream
stream.forEach(??);
return i;
}发布于 2015-10-30 15:39:51
下面的方法将返回所需的结果。
它创建一个从i到len排他(在range的帮助下)的len,然后过滤缓冲区的元素等于\n (借助filter)。当找到一个,newLine()就会被调用。因为我们只对第一个感兴趣,所以我们称之为findFirst()。如果没有找到,那么我们返回len (在orElse的帮助下)。
protected Integer skipLine(byte[] buf,Integer len, Integer i) {
return IntStream.range(i, len)
.filter(n -> buf[n] == '\n')
.peek(n -> newLine())
.findFirst()
.orElse(len-1) + 1;
}另外,您应该将输入参数更改为int而不是Integer (并且类似地,返回int而不是Integer)。
发布于 2015-11-01 06:26:25
不要把太多东西塞进一条小溪里。无论你在队伍中赢了什么,你都会在清楚的方面输掉。
如果你必须用英语来描述你的方法,你会说:“我想找到第一个行提要,它位于i和len (不包括len )之间。如果我找到了,我想打电话给newLine(),在linefeed之后马上返回索引。如果找不到,我只想返回len。”
考虑下面的实现,它读起来与方法的英文描述完全一样。
protected Integer skipLine(byte[] buf, Integer len, Integer i) {
OptionalInt linefeed = IntStream.range(i, len)
.filter(n -> buf[n] == '\n')
.findFirst();
if (linefeed.isPresent()) {
newLine();
return linefeed.getAsInt() + 1;
} else {
return len;
}
}通过使用流在linefeed之后搜索位置,然后在.orElse(len)中只有一条返回语句,您可以在不损失太多清晰度的情况下缩短它,但这是一个品味问题。
如另一个答案所建议的,请避免将peek与findFirst一起用于副作用。它依赖于未指定的行为,并可能导致惊喜。考虑以下代码(Arrays.asList的静态导入):
List<List<Integer>> numbers = asList(
asList(1, 2),
asList(3, 4)
);
int one = numbers.stream()
.flatMap(List::stream)
.peek(System.out::println)
.findFirst()
.get();这段代码输出了什么?由于您使用的是findFirst,您可能希望peek只打印流的第一个元素,即1。但是,实际上,上面的代码将打印12。peek不受约束,只对满足findFirst的元素进行严格的操作。
https://stackoverflow.com/questions/33439630
复制相似问题