Home > Net >  Find elements that are not present in a Set a return a new Set containing these missing elements
Find elements that are not present in a Set a return a new Set containing these missing elements

Time:04-04

I have an enum Tags containing a complete list of tags which can be applied to instances of the Product class. In this class there is an instance variable tags which is a Set of Strings that contains a subset of these tags. What I'm trying to do is find a set of tags that have yet to be applied to a certain product and return it as a new Set using a method .

        Set<String> suggestedTags = new HashSet<>();
        Arrays.stream(Tags.values())
                .forEach(tagsList -> {
                    if (!this.tags.contains(tagsList.getTagName())) {
                        suggestedTags.add(tagsList.getTagName());
                    }
                });
        return suggestedTags;

I have tested the above code and it works as expected. However, I wish to accomplish the same result in just one statement. Something like this:

        return Arrays.stream(Tags.values())
                .map(tagsList -> {
                    // code to find missing elements goes here
                })
                .collect(Collectors.toSet());

I'm stuck here as I'm not sure which intermediate operation would be suitable for such a task. I thought of using map() and filter() but no luck so far.

The enum Tags is as follows:

    public enum Tags {

        BIRTHDAY("birthday"),
        GRADUATION("graduation"),
        GET_WELL_SOON("get well soon");

        final String tagName;

        private Tags(String tagName) {
            this.tagName = tagName;
        }

        public String getTagName() {
            return tagName;
        }
    }

How can this be done?

CodePudding user response:

You want to filter the Tags which is not in Product, and get name of Tags the below code should work

  return Arrays.stream(Tags.values()).filter(tag -> !this.tags.contains(tag)).map(Tags::getTagName).collect(Collectors.toSet());

CodePudding user response:

You can do something like this:

Set<String> suggestedTags = Arrays.stream(Tags.values())
                                  .map(Tags::getTagName)
                                  .collect(Collectors.toCollection(HashSet::new));
suggestedTags.removeAll(tags);

but that's still two expressions. Still a lot cleaner than your first version, though.

If you switch from sets of Strings to EnumSets of Tags, though...

EnumSet<Tags> suggestedTags = EnumSet.complementOf(tags);
// Assuming EnumSet<Tags> tags = EnumSet.of(Tags.BIRTHDAY);
// suggestedTags contains GRADUATION and GET_WELL_SOON

This also has the nice side effects of making the sets a lot faster and taking up less memory.

  • Related