我在项目中遇到以下代码。我想知道是否可以通过使用Java 8流或一般通过collection API进一步对其进行优化。
private Set<Student> getFilteredSet() {
Set<Student> unfilteredSet = getAllStudents();
Set<Student> adminAreaSet = getAdminStudents();
Set<String> adminAreaID = new HashSet<>();
Set<Student> filteredSet = new HashSet<>();
for (final Student student : adminAreaSet) {
adminAreaID.add(student.getId());
}
for (final Student student : unfilteredSet) {
if (adminAreaID.contains(student.getId())) {
filteredSet.add(student);
}
}
return filteredSet;
}
注意:unfilteredSet
和adminAreaSet
拥有Student
答案 0 :(得分:8)
由于问题是用java-stream标记的,因此提高代码可读性的一种方法是将其转换为:
Set<String> adminAreaID = getAdminStudents().stream()
.map(Student::getId)
.collect(Collectors.toSet());
return getAllStudents().stream()
.filter(student -> adminAreaID.contains(student.getId()))
.collect(Collectors.toSet());
答案 1 :(得分:2)
根据您的评论,您正在寻找速度优化。有很多文章比较Stream和Collection,甚至更多有关整个Internet的文章。 我以示例的方式建议您看一下这个问题,该问题针对每个循环比较Streams和Old之间的速度性能: Java 8: performance of Streams vs Collections。 使用Stream创建大量中间对象并调用中间方法时,每个循环的速度都比基本速度慢是正常的。 但是,您可以使用流来获得更具可读性/更小的代码。
要回答这个问题,考虑到速度性能,我认为您的代码已经很好。我所看到的是您应该初始化adminAreaID,因为您确切知道它将具有的大小:
Set<String> adminAreaID = new HashSet<>(adminAreaSet.size(), 1.);
通过设置大小和负载因子,可以确保没有时间花在长大您的设备上。 根据{{3}}:
负载因子是衡量哈希表已满的程度的度量 在自动增加容量之前获得。
您必须将其设置为1,因为您不会获得更高的adminAreaSet大小。此外,如果将其设置为.75(默认值),则当循环达到其容量的75%(这是无用的)时,您的Set将增长一次。
如果没有内存问题,则应该对filteredSet进行相同的操作:
Set<Student> filteredSet = new HashSet<>(unfilteredSet.size(), 1.);
实际上,当您过滤unfilteredSet时,您不会达到最大容量,但是它将确保您在filteredSet填充期间不会长大。