有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java根据字符串数组中的单词筛选列表

我有一个由另一个应用程序发送的List<Employees>结果集

class Employee{
    Long id;
    String name;
    String gender;
    List<String> projects;
    // Getters
    // Setters
}

我需要编写一个方法或lambda表达式来使用从UI传递的一堆查询词(String[])过滤List

String[]中的任何单词都可以匹配任何变量(id、名称、性别、项目)。应返回所有具有匹配项的列表。姓名的一部分也应匹配,例如:“john”应匹配示例中的列表1和3

List<Employee> filter (empList, queryWords) {
    // code
}

你能给我指出实现这一目标的正确方向吗

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

共 (3) 个答案

  1. # 1 楼答案

    您可以将查询词数组转换为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());
    }
    

    编辑:
    正如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());
    }
    
  2. # 2 楼答案

    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;
    }
    
  3. # 3 楼答案

    写一个方法

    private boolean employeeMatchesWord(Employee employee, String word)
    

    如果雇员的至少一个字段与给定单词匹配,则返回true

    然后使用

    return empList.stream()
                  .filter(employee -> Arrays.stream(queryWords)
                                            .anyMatch(word -> employeeMatchesWord(employee, word))
                  .collect(Collectors.toList());