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

wor*_*joe 2 java enums filtering exception java-stream

我有一个枚举我通话Permission的安全权限,此事对我的申请。在数据库中,用户可能拥有与我的应用程序无关的其他权限。从数据库读取用户时,我得到 aList<String>并且我想建立 a 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());
Run Code Online (Sandbox Code Playgroud)

问题是该map步骤在到达与枚举值不对应的字符串之一时将引发异常。我怎样才能filter去掉这些值,以便在不抛出异常的情况下悄悄地忽略它们?

Rav*_*ala 5

您可以先将Permission枚举常量编码为 a Setof String,然后在filter谓词中使用它来过滤掉无效值。然后使用.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());
Run Code Online (Sandbox Code Playgroud)

不过,您最好声明一个以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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Set<Permission> appPermissions = plaintextAuthorities.stream()
    .filter(Permission::isValid)
    .map(Permission::valueOf)
    .collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)


Eug*_*ene 5

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

public enum Permission {
    ADMIN,
    USER;

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

}
Run Code Online (Sandbox Code Playgroud)

然后简单地做:

List<Permission> permissions =
        plaintextAuthorities.stream()
                            .map(Permission.MAP::get)
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)