Найти, если строка из одного набора является подстрокой строки из другого набора, используя декларативный стиль? - PullRequest
3 голосов
/ 22 марта 2020

У меня есть две Sets строк, мне нужно найти, является ли строка подстрокой какой-либо строки из другого набора. Ниже приведен эквивалентный код в императивном стиле.

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

Я придумал декларативный код, который не очень красноречив.

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

Есть ли способ написать тот же код свободно?

Ответы [ 2 ]

5 голосов
/ 22 марта 2020

Вы можете заменить комбинацию findFirst + isPresent на что-то в строках использования anyMatch, и это значительно упростит код:

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)));
0 голосов
/ 23 марта 2020

Это немного отличается от того, что вы просили. Но он сообщит вам, есть ли совпадения строк. Если в вашем вопросе не обязательно использовать потоки, я бы предпочел использовать простой для l oop, который у вас уже есть. Я удалю его своим ответом, если вы дадите мне знать, что он вам не полезен.

Код берет каждый элемент набора set2 и проверяет, есть ли для него совпадения в потоке 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;
    }

}
...