简体   繁体   中英

How do I filter out a list of enums based on some criteria?

Say I have a class:

public enum Enums
{
    // about thousand different Enums 
}

and I have another class where a user signs in, and based on whether or not hes an admin or a regular user, the user has access to a limited list of enums. I know I can get the full list of all the enums from the class, but what is an elegant way to filter these by some criteria, without the Enums class knowing about user information?

Edit: Here is a snip of what it looks like today:

@GET
@RolesAllowed({ADMIN})
@Path("/test")
public Response reply(@Auth User user)
{
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("enums", Arrays.toString(Enums.values()));
    return Response.ok(jsonObject.toJSONString()).build();
}

I am returning the full list of 1000+ events, when admin should only see a limited amount.

Let us take example of a week days name as enum. See below

public enum DaysOfWeekEnum {

    SUNDAY("off"), 
    MONDAY("working"), 
    TUESDAY("working"), 
    WEDNESDAY("working"), 
    THURSDAY("working"), 
    FRIDAY("working"), 
    SATURDAY("off");

    private String typeOfDay;

    DaysOfWeekEnum(String typeOfDay) {
        this.typeOfDay = typeOfDay;
    }

    // standard getters and setters 

    public static Stream<DaysOfWeekEnum> stream() {
        return Stream.Of(DaysOfWeekEnum.values()); 
    }
}

Now we will write an example in order to print the non-working days:

public class EnumStreamExample {

    public static void main() {
        DaysOfWeekEnum.stream()
        .filter(d -> d.getTypeOfDay().equals("off"))
        .forEach(System.out::println);
    }
}

The output we get when we run this:

SUNDAY
SATURDAY

Sorry m on phone, please format code in answer.

Let us say your enum looks like

private enum Enums {
    A,
    B,
    C,
    D
}

where A, B are admin specific.

Create a class that allows access to the Enums based on whether the person is admin or not.

public class SO {
    EnumSet<Enums> adminEnums = EnumSet.allOf(Enums.class);
    EnumSet<Enums> nonAdminEnums = EnumSet.of(Enums.C, Enums.D);

    public Set<Enums> getEnums(User user) {
        boolean isAdmin = user.isAdmin(); //An example
        return isAdmin ? adminEnums : nonAdminEnums;
    }

An EnumSet is a special Set implementation optimized for storing a set of enums. adminEnums stores the list of all enums whereas nonAdminEnums has the limited set of enums.

You either have to explicitly specify the list of restricted enums for admin or specify the open enums and derive the other based on this. Not only this is tedious but error-prone. In the future, when you add a new enum instance, you have to update this too and it is easy to forget this.

It would be better if the enums itself contained this information like,

private enum Enums {
    A(false),
    B(false),
    C(true),
    D(true);

    private boolean adminSpecific;
    Enums(boolean adminSpecific) {
        this.adminSpecific = adminSpecific;
    }

    public boolean isAdminSpecific() {
        return adminSpecific;
    } 
}

In this case, we can derive the list based on the information contained in the enum instance.

Set<Enums> adminEnums = Arrays.stream(Enums.values())
        .filter(Enums::isAdminSpecific)
        .collect(Collectors.toSet());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM