我正在学习lambda表达式。
给定一个名称列表,我想计算以N
开头的名称的数量。
我做到了:
final static List<String> friends = Arrays.asList("Brian", "Nate", "Neal", "Raju", "Sara", "Scott");
public static int countFriendsStartWithN() {
return Math.toIntExact(friends
.stream()
.filter(name -> name.startsWith("N"))
.count());
}
对count方法的调用返回一个原语long
,但我想要一个int
。
我使用Math.toIntExact
来获取long
的值int
。
是否可以直接在lambda表达式内获取int
值?
答案 0 :(得分:6)
否,不可能将对toIntExact
的调用放入方法调用链,即流管道中。这是因为count
是终端操作,并且返回原语long
,在该原语上不可能进行任何方法调用。终端操作是结束流管道并产生结果(或副作用)的操作。
因此,我相信您可以做的最好的事情就是继续使用已有的代码。恕我直言,很好。
答案 1 :(得分:5)
好吧,这是一种在不进行强制转换的情况下将计数计算为int的方法,有点愚蠢:
public static int countFriendsStartWithN() {
return friends.stream()
.filter(name -> name.startsWith("N"))
.mapToInt (s -> 1)
.sum();
}
答案 2 :(得分:4)
您无法在当前具有的lambda表达式内执行任何操作,因为这是一个谓词:它返回一个布尔值。 Math.toIntExact
返回int
。
您可以在没有Math.toIntExact
(或简单的演员表)的情况下完成此操作,
return /* create stream, filter */
.mapToInt(a -> 1).sum();
但是这可能比现在做的要慢。
答案 3 :(得分:3)
还有另一种效果并不理想的选择-可以使用套用整理器的收集器:
public static int countFriendsStartWithN() {
return friends.stream()
.filter(name -> name.startsWith("N"))
.collect(Collectors.collectingAndThen(Collectors.counting(), Math::toIntExact));
}
如果您经常需要它可能会有一个好处-您可以构建一个实用工具方法,返回此Collector
以使其可重复使用。
答案 4 :(得分:2)
这是使用reduce
public static int countFriendsStartWithN2() {
return friends
.stream()
.filter(name -> name.startsWith("N"))
.map(s -> 1)
.reduce(0, Integer::sum);
}