Find if a string from one Set is substring of string from another Set using declarative style?

599 Views Asked by At

I have two Sets of strings, I need to find if a string is substring of any string from another Set. Below is the equivalent code in imperative style.

boolean elementContains() {
    Set<String> set1 = Set.of("abc","xyz","mnop");
    Set<String> set2 = Set.of("hello.world.mnop", "hello.world", "foo.bar");

    for (String str: set1) {
        for (String str2: set2) {
            if(str2.contains(str)) { //XXX: contains not equals
                return true;
            }
        }
    }
    return false;
}

I came up with declarative code which is not very eloquent.

boolean elementContains() {
    Set<String> set1 = Set.of("abc","xyz","mnop");
    Set<String> set2 = Set.of("hello.world.mnop", "hello.world", "foo.bar");

    Optional<String> first = set1.stream()
            .filter(ele -> {
                Optional<String> first1 = set2.stream()
                        .filter(ele2 -> ele2.contains(ele))
                        .findFirst();
                return first1.isPresent();
            }).findFirst();

    return first.isPresent();
}

is there a way to write the same code fluently?

2

There are 2 best solutions below

1
Naman On BEST ANSWER

You can replace the findFirst + isPresent combination with something on the lines of using anyMatch and that would simplify the code significantly :

Set<String> set1 = Set.of("abc", "xyz", "mnop");
Set<String> set2 = Set.of("hello.world.mnop", "hello.world", "foo.bar");
return set1.stream()
        .anyMatch(ele -> set2.stream()
                .anyMatch(ele2 -> ele2.contains(ele)));
1
armani On

This is a bit different from what you requested. But, it will tell you if any string matches are present. Unless it is mandatory to use streams in your question, I would prefer to use the simple for loop which you already have. I'll delete it my answer if you let me know that it is not helpful to you.

The code takes each element of set2 and checks if there are any matches for it in a streamed set1.

import java.util.Set;
import java.util.stream.Collectors;

public class Temp {

    public static void main(String [] args){
        Set<String> set1 = Set.of("abc","xyz","mnop");
        Set<String> set2 = Set.of("hello.world.mnop", "hello.world", "foo.bar");

        Set<String> filtered = setContains(set1, set2);
        filtered.forEach(System.out::println);
    }

    //Gives a set  of elements of set2 which contain one or more elements of set1.
    public static Set<String> setContains(Set<String> set1, Set<String> set2){
        Set<String> result = set2
                .stream()
                .filter(
                        //Filter an s2 if it contains at any s1.
                        s2 -> set1
                                .stream()
                                .filter( s1 -> s2.contains(s1) )
                                //Make a set of s1's which are present in a given s2.
                                .collect( Collectors.toSet() )
                                //If the set has some values for a given s2, then we can accept that s2.
                                .size() > 0
                )
                .collect(Collectors.toSet());
        return result;
    }

}