使用java 8,现在我们可以使用java.util.Collection.stream
来执行一些集合基本功能,例如filter
,map
,collect
,anyMatch
等
问题是当你有一个Collection并且你必须使用其中的一些函数时,代码会变得有点难看,例如:
List<String> ids = this.getFriends(userId).stream().map(Friend::getFriendUserId).collect(Collectors.toList())
在这种情况下,我有一个List<Friend>
,我想要一个List<String>
,其中会填充第一个列表中每个项目的friendId。
我认为代码可能是这样的:
List<String> ids = this.getFriends(userId).map(Friend::getFriendUserId);
这当然更具可读性,也更干净,但无效,因为List
无法理解消息地图。我无法理解在Java 8中实现这个问题会是什么问题,为什么他们决定强制每次都转换为Stream
,在某些情况下我们会将其转换回Collection
就像这种情况一样。
答案 0 :(得分:2)
摆脱.stream()
非常简单。只需更新您的API即可返回流,而不是集合。同样使用复数名词命名您的方法返回流。因此,更换
public List<Friend> getFriends(String userId) { ... }
使用
public Stream<Friend> friends(String userId) { ... }
此方案在JDK中广泛使用。示例:BufferedReader.lines()
,Random.ints()
,ZipFile.entries()
,String.chars()
等等(更多内容见JDK-9)。
您可以做的第二件事是静态导入Collectors
:
import static java.util.stream.Collectors.*;
这会将Collectors.toList()
缩短为简单toList()
:
List<String> ids = this.friends(userId).map(Friend::getFriendUserId).collect(toList());
已经短得多了。
最后,您应该考虑将结果流收集到List
中是否真的有必要。有时它是合理的,但通常它只是在Java-8之前思考,就像你需要集合中的所有内容一样。例如,如果要使用此列表迭代它,为什么不使用Stream.forEach()
迭代流本身?