使用java 8流基于java对象的多个属性检索distinct元素

sea*_*gar 3 java lambda java-8 java-stream

如何使用java 8流基于多个条件从列表中获取distinct元素?

例如 - 让我们假设一个对象Person:

class Person {
    Integer id;
    String name;
}
Run Code Online (Sandbox Code Playgroud)

我想有独特的组合清单idname.
列表中可以有多个具有相同ID和名称的记录

YCF*_*F_L 6

您可以创建自己的独特方法,例如:

private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Map<Object, Boolean> seen = new ConcurrentHashMap<>();
    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
Run Code Online (Sandbox Code Playgroud)

所以你可以使用它与过滤器:

List<Person> persons = listPersons.stream()
         //@Holger suggest
        .filter(distinctByKey(pr -> Arrays.asList(pr.getId(), pr.getName())))
        .collect(toList());
Run Code Online (Sandbox Code Playgroud)

看看这个 :

如果您的列表人员是:

List<Person> listPersons = Arrays.asList(
        new Person(1, "person1"),
        new Person(1, "person5"),
        new Person(2, "person2"),
        new Person(1, "person1"),
        new Person(1, "person2"),
        new Person(1, "person1"),
        new Person(3, "person3")
);
Run Code Online (Sandbox Code Playgroud)

输出

Person{id=1, name=person1}
Person{id=1, name=person5}
Person{id=2, name=person2}
Person{id=1, name=person2}
Person{id=3, name=person3}
Run Code Online (Sandbox Code Playgroud)

  • 我强烈反对使用像`pr.getId() + " " + pr.getName()` 这样的复合键;如果任一字符串包含空格,则可能不明确,如果字符串很长,则效率低下。解决这两个问题就像使用`Arrays.asList(pr.getId(), pr.getName())` 作为键(或Java 9:`List.of(pr.getId(), pr.getName())一样简单`)… (3认同)