【问题标题】:Java Stream Filter based on a Set-type基于 Set 类型的 Java 流过滤器
【发布时间】:2020-05-17 02:34:45
【问题描述】:

有没有什么方法可以使用 Lambda Stream 根据 Set 过滤 Stream 或 List 中的 Set 字段?

例子:

    List<Person> persons = new ArrayList<Person>();
    Set<String> hobbySet1 = new HashSet<String>();
    hobbySet1.add("H1");
    hobbySet1.add("H2");
    hobbySet1.add("H3");

    Set<String> hobbySet2 = new HashSet<String>();
    hobbySet2.add("H2");
    hobbySet2.add("H4");

    Set<String> hobbySet3 = new HashSet<String>();
    hobbySet3.add("H3");

    Set<String> hobbySet4 = new HashSet<String>();
    hobbySet4.add("H4");

    persons.add(new Person("P1", hobbySet1));
    persons.add(new Person("P2", hobbySet2));
    persons.add(new Person("P3", hobbySet3));
    persons.add(new Person("P4", hobbySet4));

    Set<String> searchHobby = new HashSet<String>();
    searchHobby.add("H1");
    searchHobby.add("H3");

我想根据 searchHobby 从 List people 中筛选出爱好,以便只保留那些在 searchHobby 中指定了爱好的人。

我知道如何使用简单的 for 循环来实现这一点。

    List<Person> result = new ArrayList<Person>();

    for (String sHobby : searchHobby) {
        for (Person p : persons) {
            Set<String> pHobbySet = p.getHobbies();
            for (String pHobby : pHobbySet) {
                if (pHobby.equalsIgnoreCase(sHobby)) {
                    Optional<Person> wasAdded = result.stream().filter(s->s.getName()==p.getName()).findAny();
                    if(wasAdded.isEmpty()) {
                        result.add(p);
                        break;
                    }
                }
            }
        }
    }

我正在寻找 java Stream Filter 解决方案。


附:

public class Person {
    String name;
    Set<String> hobbies;

    public Person(String name, Set<String> hobbies) {
        this.name = name;
        this.hobbies = hobbies;
    }

    public String getName(){
        return name;
    }

    public Set<String> getHobbies(){
        return hobbies;
    }
}

【问题讨论】:

  • List&lt;Person&gt; collect = persons.stream().filter(s -&gt; s.getHobbies().containsAll(searchHobby)) .collect(Collectors.toList());
  • 请注意,在您的示例中,hobbySet3 hobbySet4 为空
  • @Ruslan,我更正了示例 [hobbySet3] 和 [hobbySet4],谢谢!

标签: java filter collections set java-stream


【解决方案1】:

你可以使用containsAll的方法找到一个人的爱好包含所有searchHobby:

List<Person> collect = persons.stream()
            .filter(person -> person.getHobbies().containsAll(searchHobby))
            .collect(Collectors.toList());

或者,如果您需要在searchHobbies 中找到至少有一个人的爱好的人,那么您可以使用removeAll

List<Person> collect = persons.stream()
            .filter(person -> new HashSet<>(person.getHobbies()).removeAll(searchHobby))
            .collect(Collectors.toList());

【讨论】:

  • removeAll 会改变人们的爱好,不是吗?
  • @Nicktar 这就是我将其包装在new HashSet&lt;&gt;(...) 中的原因。那样的话,原来的爱好就不会改变了
  • 第一个过滤器与 Vishwa Ratna 建议的相同。第二个得到与 Red_Shuhart 相同的结果,完全符合我的 for...loop 要求。谢谢大家!我学到了很多:-)
【解决方案2】:

for 循环确实处理的条件有点尴尬,次优。 一个简单的解决方案是:

List<Person> result = persons.stream()
       .filter(p -> hasHobby(p.getHobbies(), searchHobby))
       .collect(Collectors.toList());

boolean hasHobby(Set<String> personHobbies, Set<String> searchHobbies) {
    Set<String> pH = personHobbiers.stream()
            .map(String::toLowerCase).collect(Collectors.toSet());
    Set<String> sH = searchHobbiers.stream()
            .map(String::toLowerCase).collect(Collectors.toSet());
    return !pH.retainAll(sh).isEmpty();
}

这也是次优的。尤其是需要一个忽略案例是很遗憾的。 简单地走一个十字路口是很困难的。然而,有几个爱好,这应该不难。可以在开头将searchHobbies 小写。

【讨论】:

    【解决方案3】:

    你可以试试:

    persons.stream()
        .filter(p -> p.getHobbies().stream()
                .filter(searchHobby::contains)
                .findAny().isPresent()
        )
        .collect(Collectors.toList());
    

    【讨论】:

      【解决方案4】:

      如果某些爱好匹配,anyMatch 将返回 true。

      List<Person> personsWithHobby = persons.stream()
          .filter(person -> person.getHobbies().stream()
                  .anyMatch(searchHobby::contains))
          .collect(Collectors.toList());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-04
        • 1970-01-01
        • 2018-07-18
        • 2014-11-17
        • 2019-01-26
        • 1970-01-01
        • 1970-01-01
        • 2017-08-23
        相关资源
        最近更新 更多