简体   繁体   中英

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

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?

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)));

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;
    }

}

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