Java8 filter and change properties simultaneously

Reading through this article, I can filter the collection like this:

Set<Status> statusClone = cloner.deepClone(statusList).stream().filter(s -> !(s instanceof FileMetadata)).collect(Collectors.toSet());

However, I will also need to set the properties simultaneously filtering them. After filtering them, I currently iterate through each one and then set properties:

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);

Is this possible in Java8 without using foreach?

EDIT: From the comments, I agree that I can clone inside the filter. Thanks.

Answers


You could use 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());

Note the javadoc warning that it could create issues if you use a parallel stream because you are modifying state.


It would be better to initialise the status directly when cloning the original list - something like:

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());

That way you avoid state modifications during the stream.


You could write:

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());

But it's a bit awkward since we're directly mutating an Object inside the peek method.

It would be better to write a copy constructor of Status and then use map instead of peek to map each status to a new status with this constructor.


Need Your Help

Installing Kendo UI from NuGet

asp.net-mvc-3 nuget kendo-ui-mvc

I'm currently trying to install Kendo UI from NuGet and noticed an issue. I cannot find the KendoUI.dll to reference. Is it in this package, and if not, is there a way to get around that to use it

Column-wise sort or top-n of matrix

performance r sorting vectorization apply

I need to sort a matrix so that all elements stay in their columns and each column is in ascending order. Is there a vectorized column-wise sort for a matrix or a data frame in R? (My matrix is all-