函数式编程——根据条件从列表中提取第一个匹配项(Java/Guava)



我有一个以下对象的列表:

class ResourcePermissionDTO {
  PermissionType permissionType;
  ... 
}

其中PermissionType为以下enum:

public enum PermissionType {
   DENY, READ_ONLY, READ_WRITE;
}

所以,列表看起来像:

List<ResourcePermissionDTO> myResourcePermissions = ...

我想要的是返回在myResourcePermissions中发现的第一个具有最严格权限的ResourcePermissionDTO。目前我有以下,但它是有点乱,我认为可能有一个更好的方法来做它使用谷歌番石榴/功能成语?

private ResourcePermissionDTO returnTheFirstMostRestrictivePermissionFoundIn(final List<ResourcePermissionDTO> resourcePermissionDTOs) {
    if (resourcePermissionDTOs.isEmpty()) {
      return null;
    }
    final List<ResourcePermissionDTO> resourcePermissionDTOsWithReadWritePermissionOfDeny = Lists.newArrayList();
    final List<ResourcePermissionDTO> resourcePermissionDTOsWithReadWritePermissionOfReadOnly = Lists.newArrayList();
    final List<ResourcePermissionDTO> resourcePermissionDTOsWithReadWritePermissionOfReadWrite = Lists.newArrayList();
    for (final ResourcePermissionDTO resourcePermissionDTO : resourcePermissionDTOs) {
      switch (resourcePermissionDTO.getPermissionType()) {
      case DENY:
        resourcePermissionDTOsWithReadWritePermissionOfDeny.add(resourcePermissionDTO);
        break;
      case READ_ONLY:
        resourcePermissionDTOsWithReadWritePermissionOfReadOnly.add(resourcePermissionDTO);
        break;
      case READ_WRITE:
        resourcePermissionDTOsWithReadWritePermissionOfReadWrite.add(resourcePermissionDTO);
        break;
      default:
        break;
      }
    }
    if (!resourcePermissionDTOsWithReadWritePermissionOfDeny.isEmpty()) {
      return resourcePermissionDTOsWithReadWritePermissionOfDeny.get(0);
    } else if (!resourcePermissionDTOsWithReadWritePermissionOfReadOnly.isEmpty()) {
      return resourcePermissionDTOsWithReadWritePermissionOfReadOnly.get(0);
    } else if (!resourcePermissionDTOsWithReadWritePermissionOfReadWrite.isEmpty()) {
      return resourcePermissionDTOsWithReadWritePermissionOfReadWrite.get(0);
    } else {
      return null;
    }
  }

即使是命令式,也可以简化如下:

List<ResourcePermissionDTO> permissions = ...;
ResourcePermissionDTO result = null;
for (ResourcePermissionDTO p: permissions) {
    if (result == null || isStronger(p.getPermissionType(), result.getPermissionType())) {
        result = p;
        if (result.getPermissionType() == PermissionType.DENY) break; // (1)
    }
}
return result;

如果您喜欢函数式风格,您可以使用reduce()复制完全相同的(尽管没有在(1)进行短路优化)。Guava不支持reduce(),因此下面的例子是在Java 8中:

return permissions.stream().reduce((result, p) -> {
    return isStronger(p.getPermissionType(), result.getPermissionType()) ? p : result;
}).orElse(null);

我会怎么做

  1. 使ResourcePermissionDTO实现Comparable<ResourcePermissionDTO>
 class ResourcePermissionDTO implements Comparable<ResourcePermissionDTO> {
      PermissionType permissionType;
      @Override
      public int compareTo(ResourcePermissionDTO that) {
          return this.permissionType.compareTo(that.permissionType);
      }
    }
  1. 将所有DTO添加到单个列表

    List<ResourcePermissionDTO> myResourcePermissions =

  2. 使用Guava's Ordering从List中获取第一件物品

    ResourcePermissionDTO leastRestrictive = Ordering.natural().max(myResourcePermissions);

最新更新