基于 Set 类型的 Java 流过滤器



有没有办法使用 Lambda 流根据集合过滤流或列表中的 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");

我想根据搜索爱好从列表人员中过滤爱好,以便仅保留那些在搜索爱好中指定了爱好的人。

我知道如何使用简单的 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流过滤器解决方案。


附言

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

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

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

你可以试试:

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

您可以使用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());

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

最新更新