基于集合类型的Java流过滤器

基于集合类型的Java流过滤器,java,filter,collections,set,java-stream,Java,Filter,Collections,Set,Java Stream,是否有任何方法可以基于使用Lambda流的集合过滤流或列表中的集合字段 例如: List<Person> persons = new ArrayList<Person>(); Set<String> hobbySet1 = new HashSet<String>(); hobbySet1.add("H1"); hobbySet1.add("H2"); hobbySet1.add("H3"); Set

是否有任何方法可以基于使用Lambda流的集合过滤流或列表中的集合字段

例如:

    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");
List persons=new ArrayList();
Set hobbySet1=新HashSet();
hobbySet1.添加(“H1”);
hobbySet1.添加(“H2”);
hobbySet1.添加(“H3”);
Set hobbySet2=新HashSet();
hobbySet2.添加(“H2”);
hobbySet2.添加(“H4”);
Set hobbySet3=新HashSet();
hobbySet3.添加(“H3”);
Set hobbySet4=新HashSet();
hobbySet4.添加(“H4”);
人员。添加(新人员(“P1”,1));
人员。添加(新人员(“P2”,hobbySet2));
新增(新人员(“P3”,第3页));
新增(新人员(“P4”,hobbySet4));
Set searchHobby=newhashset();
添加(“H1”);
添加(“H3”);
我想根据searchHobby从列表中筛选嗜好,以便只保留那些在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;
                    }
                }
            }
        }
    }
List result=new ArrayList();
用于(字符串sHobby:searchHobby){
用于(人员p:人员){
设置pHobbySet=p.get嗜好();
for(字符串pHobby:pHobbySet){
if(pHobby.equalsIgnoreCase(sHobby)){
可选的wasAdded=result.stream().filter(s->s.getName()==p.getName()).findAny();
if(wasAdded.isEmpty()){
结果:添加(p);
打破
}
}
}
}
}
我正在寻找java流过滤器解决方案。


p.S.个人

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;
    }
}
公共类人物{
字符串名;
设置爱好;
公众人物(字符串名称、设置爱好){
this.name=名称;
这个。爱好=爱好;
}
公共字符串getName(){
返回名称;
}
公共集{
回归爱好;
}
}
您可以使用该方法找到一个爱好包含所有
搜索爱好的人

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

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();
}
列表结果=persons.stream()
.filter(p->hasHobby(p.gethobby(),searchHobby))
.collect(Collectors.toList());
布尔hasHobby(设置个人爱好,设置搜索爱好){
设置pH=personHobbiers.stream()
.map(字符串::toLowerCase).collect(收集器.toSet());
Set sH=searchHobbiers.stream()
.map(字符串::toLowerCase).collect(收集器.toSet());
return!pH.retainal(sh.isEmpty();
}
这也是次优的。尤其是一个需要忽略的案例。 简单地走十字路口是很难的。然而,有几个爱好,这应该不难。一开始可以用小写字母
搜索爱好

您可以尝试:

persons.stream()
.filter(p->p.getHabiods().stream())
.filter(searchHobby::contains)
.findAny().isPresent())
)
.collect(Collectors.toList());
如果某些爱好匹配,则返回true

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

List collect=persons.stream().filter(s->s.gethabiods().containsAll(searchhabiody)).collect(Collectors.toList())注意,在您的示例中,
hobbySet3
hobbySet4
是empty@Ruslan,我更正了示例[hobbySet3]和[hobbySet4],谢谢!removeAll会改变人们的兴趣爱好,不是吗?@Nicktar这就是为什么我把它包装在
新的HashSet(…)
中。在这种情况下,最初的爱好不会改变。第一个过滤器与Vishwa Ratna建议的相同。第二个得到了与Red_Shuhart相同的结果,完全满足了我的for…loop要求。谢谢大家!我学到了很多:-)
List<Person> personsWithHobby = persons.stream()
    .filter(person -> person.getHobbies().stream()
            .anyMatch(searchHobby::contains))
    .collect(Collectors.toList());