有 Java 编程相关的问题?

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

用于过滤对象的Java lambda函数

我有几个person对象和一个为给定实体id选择person的函数:

person1 = {
    name = "abc";
    id = "1";
}
person2 = {
    name = "xyz";
    id = "2";
}
person3 = {
    name = "aaa";
    id = null;
}

Person getPersonFunction(List<Person> persons, String id) {
   //Get the person for the given id and if id is not for any person from the list then select the person with null as id.
}

问题是:我想为给定的实体id选择一个人,如果给定实体id的列表中没有这样的人,那么选择实体id设置为null的人。这些人总是一个人,其实体id设置为null,就像一个默认的人一样。 我可以使用for循环轻松地解决这个问题,但我想使用java流解决这个问题。 以下是我所做的:

Map<String, Person> personMap = persons.stream().collect(Collectors.toMap(Person::id, person -> person);

Person person = personMap.getOrDefault(id, personMap.get(null))

这给了我正确的结果,但我想在一行中完成


共 (4) 个答案

  1. # 1 楼答案

    如果找不到人,您可以再次流式传输(这显然不是最佳的)

    persons.stream()
           .filter(person -> person.getId().equals(id))
           .findFirst()
           .orElse(persons.stream()
                          .filter(person -> person.getId() == null)
                          .findFirst()
                          .orElseThrow(() -> new RuntimeException("No default person found")));
    

    另一种选择是使用有状态映射来存储(并记住)Person将nullid(同样听起来不太好)

  2. # 2 楼答案

    由于没有为错误案例定义行为,因此可以使用

    Person getPersonFunction(List<Person> persons, String id) {
       return persons.stream()
            .max(Comparator.comparingInt(p -> id.equals(p.id())? 1: p.id()==null? 0: -1))
            .get(); // throws NoSuchElementException if list is empty
    }
    

    这取决于您的语句,即始终存在具有nullid的人员。否则,当列表为空时,将抛出NoSuchElementException,但更糟糕的是,如果既不存在匹配的id也不存在nullid,则将返回任意人员(第一个)

    请注意,循环将更简单更有效:

    Person getPersonFunction(List<Person> persons, String id) {
        Person nullId = null;
        for(Person p: persons)
            if(id.equals(p.id())) return p; else if(p.id()==null) nullId = p;
        return Objects.requireNonNull(nullId, "no person with null id in list");
    }
    

    这更有效,因为当找到匹配项时,它将立即返回,同时仍然能够在不进行其他搜索操作的情况下提供回退

  3. # 3 楼答案

    做这件事最明显的方法就是

    Person NOBODY = new Person("NOBODY", null);
    
    private Person findPerson(List<Person> people, String id) {
        return people.stream()
                // Anyone with the right or null id.
                .filter(p -> p.id == null || p.id.equals(id))
                // Sort putting null ids at the end.
                .sorted(Comparator.comparing(p -> p.id == null))
                // Take first.
                .findFirst()
                // Should never happen.
                .orElse(NOBODY);
    }
    
  4. # 4 楼答案

    我建议避免使用流API来消除行;这不是它的目的

    你处理收集和绘制地图的想法很好。您还可以重用地图,如果您试图将其强制为一行,这是不可能的。此外,构建地图然后使用它来吸引满足您的约束的人之间的明显区别是自文档化(它使人们更容易理解您的代码)

    更多地考虑可读性和算法设计。少考虑如何用最少的行数完成任务

    当然,这并不是说您不应该减少代码重复