Java 中的 Collectors 详解

在 Java 中,Stream API 为我们提供了一种处理数据的现代化方式。但在进行过滤、映射和转换操作之后,我们通常需要将结果收集到一个集合、一个 Map,甚至是单个值中。

这就是 Collectors 大显身手的地方。

  • Collector 是一个对象,它定义了如何将 Stream 中的元素累积到最终结果中。
  • Collectors 工具类提供了现成的静态方法供我们使用,因此我们几乎不需要自己编写收集器。

实现 City 类的 Java 程序

让我们首先定义一个 City 类来准备我们的数据模型。

public class City {

    private String name;
    private double temperature;

    // 带参数的构造函数
    public City(String name, double temperature) {
        this.name = name;
        this.temperature = temperature;
    }

    // Getter 方法
    public String getName() { return name; }
    public Double getTemperature() { return temperature; }

    // 重写 toString 方法以便于显示
    @Override
    public String toString() {
        return name + " --> " + temperature;
    }
}

我们还需要创建一个辅助方法来准备样本数据:

private static List prepareTemperature() {
    List cities = new ArrayList();
    cities.add(new City("New Delhi", 33.5));
    cities.add(new City("Mexico", 14));
    cities.add(new City("New York", 13));
    cities.add(new City("Dubai", 43));
    cities.add(new City("London", 15));
    cities.add(new City("Alaska", 1));
    cities.add(new City("Kolkata", 30));
    cities.add(new City("Sydney", 11));
    cities.add(new City("Mexico", 14));  // 重复数据
    cities.add(new City("Dubai", 43));   // 重复数据
    return cities;
}

常用的 Collectors 方法

1. toList()

toList() 方法将输入元素转换为一个新的 List,并返回一个 Collector。

下面的程序演示了如何实现 toList() 方法:

import java.util.ArrayList; 
import java.util.List; 
import java.util.stream.Collectors; 
  
public class Main { 
  
    public static void main(String[] args) 
    { 
  
        System.out.println(prepareTemperature().stream()
                 .filter(f -> f.getTemperature() > 10)
                 .map(f -> f.getName())
                 .collect(Collectors.toList())); 
    } 
}

输出:

> [New Delhi, Mexico, New York, Dubai, London, Kolkata, Sydney, Mexico, Dubai]

2. toSet()

toSet() 方法将输入元素转换为一个新的 Set 并返回一个 Collector。这个方法会返回一个不包含重复元素的集合。

下面的程序演示了如何实现 toSet() 方法:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
 
public class Main {
 
    public static void main(String[] args)
    {
 
        System.out.println(prepareTemperature()
                .stream()
                .filter(f -> f.getTemperature() > 10)
                .map(f -> f.getName())
                .collect(Collectors.toSet()));
        }
}

输出:

> [New York, New Delhi, London, Mexico, Kolkata, Dubai, Sydney]

在这里,我们可以注意到输出结果中 Mexico 和 Dubai 没有重复出现。

3. toCollection(Supplier collectionFactory)

INLINECODEbc570311 方法将 Stream 元素收集到用户定义的集合中,这与使用默认类型的 INLINECODE16b24b13 或 INLINECODE27d3ddb8 不同。其中,INLINECODE3ec1f0dd 是目标集合类型,T 是元素类型。

下面的程序演示了如何实现 toCollection() 方法:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
 
public class Main {
 
    public static void main(String[] args)
    {
        System.out.println(prepareTemperature()
                .stream()
                .map(f -> f.getName())
                .collect(Collectors.toCollection(LinkedList::new)));
    }
}

输出:

> [New Delhi, Mexico, New York, Dubai, London, Alaska, Kolkata, Sydney, Mexico, Dubai]

4. toMap()

toMap(Function keyMapper, Function valueMapper) 方法将元素转换为一个 Map

下面的程序演示了如何实现 toMap() 方法:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Map;
 
public class Main {
 
    public static void main(String[] args)
    {
        // 这里,我们将名称定义为 Key,温度定义为 Value
        Map cityTempMap = prepareTemperature()
                .stream()
                .filter(city -> city.getTemperature() > 10)
                .collect(Collectors.toMap(City::getName, City::getTemperature));
                 
        System.out.println(cityTempMap);
    }
}

输出:

> {New Delhi=33.5, Mexico=14.0, New York=13.0, Dubai=43.0, London=15.0, Kolkata=30.0, Sydney=11.0}

注意:如果 Stream 中存在重复的 Key(例如上面的例子中有两个 "Mexico"),直接使用 toMap 可能会抛出 IllegalStateException。为了避免这种情况,我们需要提供合并函数来处理冲突。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/29114.html
点赞
0.00 平均评分 (0% 分数) - 0