『面试の神』Java如何实现DistinctBy?

「这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战」。

1.前言

Hello 大家好,我是l拉不拉米,在列表中搜索不同元素是我们程序员通常面临的常见任务之一。从包含 Streams 的 Java 8 开始,我们有了一个新的 API 来使用函数式方法处理数据。

在本文中,我们将展示4种使用列表中对象的特定属性过滤集合的方法。

2. 使用Stream API

Stream API 提供了 distinct() 方法,该方法基于 Object 类的 equals() 方法返回列表的不同元素。

但是,如果我们想按特定属性进行过滤,它会变得不那么灵活。我们的替代方案之一是编写一个过滤器来维护状态。

2.1.使用状态过滤器

解决方案之一是实现有状态的 Predicate

public 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; 
}
复制代码

为了测试它,我们将使用以下具有属性 age、email 和 name 的 Person 类:

public class Person { 
    private int age; 
    private String name; 
    private String email; 
    // getters and setters 
}
复制代码

按名称获取新的过滤集合

List<Person> personListFiltered = personList.stream()
    .filter(distinctByKey(p -> p.getName()))
    .collect(Collectors.toList());
复制代码

3. 使用 Eclipse Collections

Eclipse Collections 是一个Java类库,它提供了在 Java 中处理流和集合的附加方法。

3.1.使用 ListIterate.distinct()

ListIterate.distinct() 方法允许我们使用各种 HashingStrategies 过滤流。这些策略可以使用 lambda 表达式或方法引用来定义。

如果我们想按人名过滤:

List<Person> personListFiltered = ListIterate
    .distinct(personList, HashingStrategies.fromFunction(Person::getName));
复制代码

或者,如果我们要使用的属性是原始属性(int、long、double),我们可以使用这样的专用函数:

List<Person> personListFiltered = ListIterate.distinct( 
    personList, HashingStrategies.fromIntFunction(Person::getAge));
复制代码

3.2. Maven 依赖

<dependency> 
    <groupId>org.eclipse.collections</groupId> 
    <artifactId>eclipse-collections</artifactId> 
    <version>8.2.0</version> 
</dependency>
复制代码

4. 使用 Vavr (Javaslang)

这是 Java 8 的函数库,提供不可变数据和函数控制结构。

4.1.使用 List.distinctBy

为了过滤列表,该类提供了自己的 List 类,该类具有 distinctBy() 方法,允许我们按其包含的对象的属性进行过滤:

List<Person> personListFiltered = List.ofAll(personList) 
    .distinctBy(Person::getName) 
    .toJavaList();
复制代码

4.2. Maven 依赖

<dependency> 
    <groupId>io.vavr</groupId> 
    <artifactId>vavr</artifactId> 
    <version>0.9.0</version> 
</dependency>
复制代码

5. 使用 StreamEx

该库为 Java 8 流处理提供了有用的类和方法。

5.1.使用 StreamEx.distinct

在提供的类中是 StreamEx,它具有 distinct 方法,我们可以向该方法发送对要区分的属性的引用:

List<Person> personListFiltered = StreamEx.of(personList) 
    .distinct(Person::getName) 
    .toList();
复制代码

5.2. Maven 依赖

<dependency> 
    <groupId>one.util</groupId> 
    <artifactId>streamex</artifactId> 
    <version>0.6.5</version> 
</dependency>
复制代码

6.最后

创作不易,如果觉得这篇文章对您有所帮助,还请多多关注,多多点赞!!感谢!!

おすすめ

転載: juejin.im/post/7032176441923993636