Java8同时过滤和更改属性

时间:2015-10-02 15:45:10

标签: java lambda java-8 java-stream

通过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中使用吗?

编辑: 从评论中,我同意我可以克隆过滤器。感谢。

2 个答案:

答案 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,使用此构造函数将每个状态映射到新状态。