通过this article阅读,我可以像这样过滤集合:
Set<Status> statusClone = cloner.deepClone(statusList).stream().filter(s -> !(s instanceof FileMetadata)).collect(Collectors.toSet());
但是,我还需要设置属性同时过滤它们。 过滤它们之后,我目前遍历每个,然后设置属性:
for (Iterator<Status> iterator = statusClone.iterator(); iterator.hasNext();)
{
Status s = iterator.next();
// if (s instanceof FileMetadata)
// {
// iterator.remove();
// continue;
// }
s.setStatus(JobStatus.UNINITIATED);
s.setLastAccessedTime(0);
s.setOffSet(null);
s.setStreamNo(null);
}
statusList.addAll(statusClone);
在没有使用foreach的情况下,这可能在Java8中使用吗?
编辑: 从评论中,我同意我可以克隆过滤器。感谢。
答案 0 :(得分:6)
您可以使用peek
:
private static void initStatus(Status s) {
s.setStatus(JobStatus.UNINITIATED);
s.setLastAccessedTime(0);
s.setOffSet(null);
s.setStreamNo(null);
}
Set<Status> statusClone = cloner.deepClone(statusList).stream()
.filter(s -> !(s instanceof FileMetadata))
.peek(MyClass::initStatus)
.collect(Collectors.toSet());
注意the javadoc警告,如果您使用并行流,则可能会出现问题,因为您正在修改状态。
最好在克隆原始列表时直接初始化状态 - 如:
private static Status cloneAndInitStatus(Status s) {
Status clone = new Status(s);
clone.setStatus(JobStatus.UNINITIATED);
clone.setLastAccessedTime(0);
clone.setOffSet(null);
clone.setStreamNo(null);
return clone;
}
Set<Status> statusClone = statusList.stream()
.filter(s -> !(s instanceof FileMetadata))
.map(MyClass::cloneAndInitStatus)
.collect(Collectors.toSet());
这样就可以避免流中的状态修改。
答案 1 :(得分:1)
你可以写:
Set<Status> statusClone = cloner.deepClone(statusList)
.stream()
.filter(s -> !(s instanceof FileMetadata))
.peek(s -> {
s.setStatus(JobStatus.UNINITIATED);
s.setLastAccessedTime(0);
s.setOffSet(null);
s.setStreamNo(null);
})
.collect(Collectors.toSet());
但是因为我们直接在peek
方法中改变了一个对象,所以有点尴尬。
最好编写Status
的复制构造函数,然后使用map
代替peek
,使用此构造函数将每个状态映射到新状态。