Home > database >  How to limit user to choose just two enums from list using Java Streams?
How to limit user to choose just two enums from list using Java Streams?

Time:10-25

I have an enum class from which user can choose up to 2 options. If he chooses more than 2 an error message should be displayed.

I would like to do this using Java streams. I am still trying to figure out how they work.

So far I came up with this piece of code under:

public enum UserSkills {

    HARD_WORKNG("HARD_WORKNG"),
    ON_TIME("ON_TIME"),
    HONEST("HONEST");

    public final String value;

    UserSkills(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return name()   "["   value   "]";
    }

    public static List < UserSkills > of (String userSkills) {
        notNull(userSkills, "userSkills cannot be null");
        return Arrays.stream(values())
            .flatMap(s - > {
                if (values().length > 3) {
                    throw new IllegalArgumentException(String.format("you can only choose up to 3 user skills", userSkills));
                } else {

                }
            }).collect(Collectors.toList());
    }
}

I am not sure how to finish it any advice appreciated.

CodePudding user response:

It seems that the method of should accept a vararg String ... userSkills (or the input String should be split somehow to identify multiple enum values):

public static List<UserSkills> of (String ... userSkills) {
    List<UserSkills> result = Arrays.stream(userSkills)
        .filter(Objects::nonNull)
        .map(UserSkills::valueOf) // throws IllegalArgumentException no enum constant
        .distinct()
        .collect(Collectors.toList());
        
    if (result.size() > 2) {
        throw new IllegalArgumentException("Only 2 skills can be selected");
    }
    return result;
}

Test:

List<UserSkills> skills = UserSkills.of(null, "HARD_WORKNG", "HONEST", "HARD_WORKNG", "ON_TIME");

Exception in thread "main" java.lang.IllegalArgumentException: Only 2 skills can be selected
List<UserSkills> skills = UserSkills.of(null, "HARD_WORKNG", "HONEST", "HARD_WORKNG");
System.out.println(skills);

Output:

[HARD_WORKNG[HARD_WORKNG], HONEST[HONEST]]

CodePudding user response:

There are lots of reasons to use streams but this is not one of them. In fact, imo, it is overkill for a simple task. I would recommend you do it similar to something like this.

public class UserSkillsDemo {
    public static void main(String[] args) {
      List<UserSkills> list = UserSkills.of("HARD_WORKING", "HONEST");  
      System.out.println(list);
    }
}

Prints

[HARD_WORKING[HARD_WORKING], HONEST[HONEST]]
  • the of method simply accepts two strings of the enum types and returns them if:
    • neither is null and
    • they are both different.
  • then it returns the two enums in a fixed size list for use as you require.
enum UserSkills {
    
    HARD_WORKING("HARD_WORKING"), ON_TIME("ON_TIME"), HONEST("HONEST");
    
    private final String value;
    UserSkills(String value) {
        this.value = value;
    }
    
    @Override
    public String toString() {
        return name()   "["   value   "]";
    }
    
    public static List<UserSkills> of(String skill1, String skill2) {
        Objects.requireNonNull(skill1,
                "userSkills cannot be null");
        Objects.requireNonNull(skill2,
                "userSkills cannot be null");
        if (skill1.equals(skill2)) {
            throw new IllegalArgumentException("Skills must be different");
        }
       
        return List.of(UserSkills.valueOf(skill1),
                UserSkills.valueOf(skill2));
    }
}

I don't now how this would used but even with a fixed sized list, an immutable list, etc there is nothing to prevent a user from copying the returned list, creating a new one and replacing or adding additional skills. So the invariants enforced in the of method don't do much no matter how they are implemented.

  • Related