在Java8流中,如何过滤出不是枚举有效值的字符串?

hmtdttj4  于 2021-07-12  发布在  Java
关注(0)|答案(3)|浏览(455)

我有一个枚举 Permission 对我的应用程序很重要的安全权限。在数据库中,用户可能具有与我的应用程序无关的其他权限。从数据库读取用户时,我得到一个 List<String> 我想建立一个 List<Permission> ,忽略那些不是枚举值的字符串。

public enum Permission { ADMIN, USER }

List<String> plaintextAuthorities = List.of("ADMIN","USER","COFFEEMAKER")

List<Permission> appPermissions = plaintextAuthorities.stream()
        .map(Permission::valueOf) // this will throw an IllegalArgumentException for 'COFFEEMAKER'
        .collect(Collectors.toList());

问题是 map 步骤到达与枚举值不对应的某个字符串时将引发异常。我该怎么办 filter 删除这些值,以便在不抛出异常的情况下悄悄忽略它们?

hsvhsicv

hsvhsicv1#

你可以先对 Permission 将常量枚举到 Set 然后在你的 filter 用于筛选无效值的 predicate 。然后使用 .map 运算符将枚举常量从字符串表示形式解码回来,仅用于有效值。下面是它的样子。

Set<String> strPermissionSet = Arrays.stream(Permission.values())
    .map(Permission::name)
    .collect(Collectors.toSet());

Set<Permission> appPermissions = plaintextAuthorities.stream()
    .filter(strPermissionSet::contains)
    .map(Permission::valueOf)
    .collect(Collectors.toSet());

不过,最好还是声明一个名为 isValid 在枚举类型中,以便给定一个字符串值,用户可以检查它是否表示有效的枚举常量。下面是它的样子。

public enum Permission {
    ADMIN, USER;

    private static final Set<String> strPermissions = 
        Arrays.stream(values())
        .map(Permission::name)
        .collect(Collectors.toSet());

    public static boolean isValid(String val) {
        return strPermissions.contains(val);
    }
}

现在您的客户端代码应该如下所示:

Set<Permission> appPermissions = plaintextAuthorities.stream()
    .filter(Permission::isValid)
    .map(Permission::valueOf)
    .collect(Collectors.toSet());
lokaqttq

lokaqttq2#

您可以将名称保留在枚举本身中(作为 Map ):

public enum Permission {
    ADMIN,
    USER;

     static final Map<String, Permission> MAP =
        EnumSet.allOf(Permission.class)
               .stream()
               .collect(Collectors.toUnmodifiableMap(
                   Enum::name,
                   Function.identity()
               ));        

}

然后简单地做:

List<Permission> permissions =
        plaintextAuthorities.stream()
                            .map(Permission.MAP::get)
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());
ogsagwnx

ogsagwnx3#

拉文德拉和尤金都给出了很好的答案。我自己的答案不那么优雅,而且速度可能较慢,但它确实有一个优点:我可以实现它,而不必修改enum类。在调用类中,我添加了一个方法:

private boolean isAValidPermission(String s) {
    try {
        Permission.valueOf(s);
        return true;
    } catch(IllegalArgumentException e) {
        return false;
    }
}

并在流表达式中添加了一个“过滤器”:

List<Permission> appPermissions = plaintextAuthorities.stream()
    .filter(this::isAValidPermission)
    .map(Permission::valueOf)
    .collect(Collectors.toList());

相关问题