Check if an arraylist contains two strings

Viewed 116

I have an pojo class like the one below

public CategoryModel {

public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

}

I have an arraylist created like the one below.

List<CategoryModel> variantCategoryModelList = new ArrayList<>();
CategoryModel cat1= new CategoryModel();
cat1.setName(TEST1);
CategoryModel cat2= new CategoryModel();
cat2.setName(TEST1);
list.add(cat1);
list.add(cat2);

I have to check, if the value "TEST1" & "TEST2" present in the list and return "true" if both values present in the "list" and I tried something like the one below, though my "list" has both the values, its returning false.Could you please help me check what I am doing wrong btw I am using JDK 11.

final Optional<CategoryModel> optionalData = variantCategoryModelList.stream().
                filter(valueData -> TEST1.equalsIgnoreCase(valueData.getName())
                        && TEST2.equalsIgnoreCase(valueData.getName())).findFirst();

        if(optionalData.isPresent()){
            return true;
        }
3 Answers

You could map your CategoryModel to name and collect to list of strings and call List.containsAll :

return variantCategoryModelList.stream()
                               .map(CategoryModel::getName)
                               .collect(Collectors.toList())
                               .containsAll(Arrays.asList("TEST1","TEST2"));

Set would be a more natural (and faster) data structure:

return variantCategoryModelList.stream()
                       .map(CategoryModel::getName)
                       .collect(Collectors.toSet())
                       .containsAll(Set.of("TEST1", "TEST2"));

Your problem was and (&&) instead of or.

So:

Set<String> soughtNames = Set.of("TEST1", "TEST2");
return variantCategoryModelList.stream()
                       .filter(cm -> soughtNames.contains(cm.getName()))
                       .distinct()
                       .count() == 2L;

As @fps commented, distinct() is needed on a list to prevent ["Test1", "Test1"] to be accepted, or ["Test1", "Test1", "Test2"] failing.

This is obviously inefficient as it will - having found 2 entries -, still walk to the end.

You want:

Set<String> soughtNames = Set.of("TEST1", "TEST2");
return soughtNames.stream()
    .allMatch(soughtName ->
         variantCategoryModelList.stream()
             .anyMatch(cm -> soughtName.equals(cm.getName()));

Or a bit retro-style:

return
    variantCategoryModelList.stream()
             .anyMatch(cm -> "TEST1".equals(cm.getName())) &&
    variantCategoryModelList.stream()
             .anyMatch(cm -> "TEST2".equals(cm.getName()));

Here's a way to do it:

Set<String> set = Set.of("TEST1", "TEST2");
boolean result = list.stream()
    .filter(cat -> set.contains(cat.getName().toUpperCase())
    .distinct()
    .limit(2)
    .count() == 2L;

This streams the list of categories, then keeps only those categories whose name is either TEST1 or TEST2. We then remove duplicates and stop after we've found two (already distinct) category names. This ensures short-circuiting. Finally, we check if we have exactly two elements at the end.

Related