[英]Filter a List based on words from String Array
I have a result set having List<Employees>
sent by another application. 我有一个结果集,其中包含由其他应用程序发送的
List<Employees>
。
class Employee{
Long id;
String name;
String gender;
List<String> projects;
// Getters
// Setters
}
I need to write a method or lambda expression to filter the List
using a bunch of query words ( String[]
) passed from the UI. 我需要编写一个方法或lambda表达式来使用从UI传递的一堆查询字(
String[]
)来过滤List
。
Any word in the String[]
can match any variable (id, name, gender, projects). String[]
中的任何单词都可以匹配任何变量(id,name,gender,projects)。 All List which have a match should be returned. 应返回所有匹配的列表。 part of name should also match eg: "john" should match List 1 and 3 in the example.
名称的一部分也应该匹配,例如:“john”应匹配示例中的列表1和3。
List<Employee> filter (empList, queryWords) {
// code
}
Can you point me in the right direction to achive this? 你能指出我正确的方向来实现这一目标吗?
example:
List:
1. 121, john doe , male , (proj1)
2. 125, sam , female, (proj4 proj5 proj9)
3. 129, john lam , male , (proj1 proj2 proj5)
4. 143, peter pan , male , (proj4 proj8)
5. 151, linda , female, (proj8 proj7 proj3 proj11)
Search Query Words:
1. "female" "proj3"- should return only No.5
2. "proj5" - should return only No.2 and 3
3. "john" - should return No.1 and 3
4. "pan" - should return No.4
Write a method 写一个方法
private boolean employeeMatchesWord(Employee employee, String word)
that returns true if at least one field of the employee matches the given word. 如果员工的至少一个字段与给定的单词匹配,则返回true。
Then use 然后用
return empList.stream()
.filter(employee -> Arrays.stream(queryWords)
.anyMatch(word -> employeeMatchesWord(employee, word))
.collect(Collectors.toList());
public List<Employee> filter(empList, queryWords){
List<Employee> result = new ArrayList<Employee>();
// look at each employee in the list
for(Employee employee : empList){
// look at each query string
for(String queryWord : queryWords){
// if any of the employee fields matches the query word,
// add it to our list and move to next employee
if(employee.name.equals(queryWord) ||
employee.gender.equals(queryWord) ||
employee.id.toString().equals(queryWord) ||
isQueryInList(queryWord, employee.projects)) {
// add it to your results
result.add(employee);
// quit looking at the rest of the queryWords,
// we found one, thats enough, move on to the next employee
break;
}
}
}
return result;
}
private boolean IsQueryInList(String queryWord, List<String> items){
//check each item in the list to see if it matches the queryWord
for(String item : items){
if(queryWord.equals(item)) {
return true;
}
}
//if we didn't find any item that matches, return false
return false;
}
You could convert the query words array to a Set
, create a Set
of properties from all the employee's members, and use retainAll
to determine which employees have at least one of the query words: 您可以将查询字数组转换为
Set
,从所有员工的成员创建一Set
属性,并使用retainAll
确定哪些员工至少有一个查询字:
public static List<Employee> filter (List<Employee> empList, String[] queryWords) {
Set<String> queryWordsSet = new HashSet<>(Arrays.asList(queryWords));
return empList.stream().filter(e -> {
Set<String> properties = new HashSet<>(e.getProjects());
properties.addAll
(Arrays.asList(e.getId().toString(), e.getName(), e.getGender()));
properties.retainAll(queryWordsSet);
return !properties.isEmpty();
}).collect(Collectors.toList());
}
EDIT: 编辑:
As JB Nizet commented, the retainAll
can be elegantly replaced with an anyMatch
expression: 正如JB Nizet评论的那样,
retainAll
可以用anyMatch
表达式优雅地替换:
public static List<Employee> filter (List<Employee> empList, String[] queryWords) {
Set<String> queryWordsSet = new HashSet<>(Arrays.asList(queryWords));
return empList.stream().filter(e -> {
Set<String> properties = new HashSet<>(e.getProjects());
properties.addAll
(Arrays.asList(e.getId().toString(), e.getName(), e.getGender()));
return properties.stream().anyMatch(queryWordsSet::contains);
}).collect(Collectors.toList());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.