Java 8 stream and set attribute from call Boolean method

Viewed 2222

Please can you help me resolve this issue I am having when attempting to stream through an array list and call a setter based on a method which returns a Boolean.

Written as a for loop, it would look like this:-

for (final PersonDto person : personList) {
    person.setUserCanEdit(userHasWriteRole(person));
}

private Boolean userHasWriteRole(final PersonDto person) {
        return getUserRoles().contains(getReadRole());
    }

I have tried a few variations with no success, along the following lines

final List<PersonDto> results = personList.stream().filter(a -> a.setUserCanEdit(this::userHasWriteRole)).collect(Collectors.toList());

... But it complains with The target type of this expression must be a functional interface

4 Answers

I think I would go for:

personList.stream()
   .filter(p -> userHasWriteRole(p))
   .forEach(p -> p.setUserCanEdit(true));

I think this keeps the intent clear,

Since you are updating the objects in array list, you can use forEach

personList.forEach(person ->person.setUserCanEdit(userHasWriteRole(person)));

The filter() method is an intermediate operation of the Stream interface that allows us to filter elements of a stream that match a given Predicate. You can't update data in the filter. Use forEach for this.

personList.stream().forEach(a -> a.setUserCanEdit(userHasWriteRole(a)));

And if you want to get in new arraylist make a copy of list and do this operations on new list

List<PersonDto> copy = new ArrayList<>(personList);
copy.stream().forEach(a -> a.setUserCanEdit(userHasWriteRole(a)));

If you want to have a list with filtered elements and do the setUserCanEdit on every elements in that list; you can do like this:

List<PersonDto> newList = personList.stream()
  .filter(p -> userHasWriteRole(p))
  .collect(Collectors.toList());

newList.forEach(p -> p.setUserCanEdit(true));
Related