【问题标题】:Find if a string from one Set is substring of string from another Set using declarative style?使用声明式样式查找一个 Set 中的字符串是否是另一个 Set 中的字符串的子字符串?
【发布时间】:2020-03-22 14:05:05
【问题描述】:

我有两个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();
}

有没有办法流畅地编写相同的代码?

【问题讨论】:

标签: java java-8 java-stream declarative-programming


【解决方案1】:

您可以将 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)));

【讨论】:

  • 看起来更好:)
【解决方案2】:

这与您要求的有点不同。但是,它会告诉您是否存在任何字符串匹配项。除非在您的问题中必须使用流,否则我更愿意使用您已经拥有的简单 for 循环。如果你让我知道它对你没有帮助,我会删除它。

代码获取 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;
    }

}

【讨论】:

  • .collect( Collectors.toSet() ) .size() &gt; 0 通过创建和填充包含所有匹配项的集合来浪费资源,只是为了找出是否至少有一个。 anyMatch 甚至 OP 的 findFirst().isPresent() 将在第一场比赛时停止处理。
猜你喜欢
  • 1970-01-01
  • 2019-05-11
  • 2012-11-23
  • 2013-05-12
  • 2011-02-07
  • 1970-01-01
  • 2015-03-21
  • 1970-01-01
相关资源
最近更新 更多