Java Stream mapToInt 深度解析
简介
在 Java 编程中,Stream API 是一个强大的工具,它为处理集合和数组提供了一种函数式、声明式的方式。mapToInt
是 Stream API 中的一个重要方法,它允许将流中的元素映射为 int
类型的值,然后可以进行各种聚合操作。本文将详细介绍 mapToInt
的基础概念、使用方法、常见实践以及最佳实践,帮助你更好地理解和运用这一特性。
目录
- 基础概念
- 使用方法
- 从对象流映射到
int
流 - 从数组创建流并映射到
int
流
- 从对象流映射到
- 常见实践
- 计算总和
- 获取最大值
- 获取平均值
- 最佳实践
- 避免装箱和拆箱
- 结合其他 Stream 操作
- 小结
- 参考资料
基础概念
mapToInt
是 java.util.stream.Stream
接口中的一个方法,它用于将流中的每个元素映射为一个 int
类型的值。这个方法返回一个 IntStream
,这是一个专门用于处理 int
类型数据的流。IntStream
提供了许多聚合操作,如 sum()
、max()
、average()
等,使得对 int
类型数据的处理更加方便和高效。
使用方法
从对象流映射到 int
流
假设我们有一个包含 Person
对象的列表,每个 Person
对象有一个 age
属性,我们想要获取所有人的年龄组成的 int
流。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
class Person {
private int age;
public Person(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
public class StreamMapToIntExample {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person(25));
people.add(new Person(30));
people.add(new Person(35));
IntStream ageStream = people.stream()
.mapToInt(Person::getAge);
ageStream.forEach(System.out::println);
}
}
在上述代码中,我们首先创建了一个 Person
类,然后创建了一个包含多个 Person
对象的列表。接着,我们使用 stream()
方法将列表转换为流,再通过 mapToInt
方法将每个 Person
对象映射为其 age
属性对应的 int
值,最终得到一个 IntStream
。最后,我们使用 forEach
方法打印出流中的每个年龄值。
从数组创建流并映射到 int
流
如果我们有一个包含字符串数字的数组,想要将其转换为 int
流进行进一步处理。
import java.util.stream.IntStream;
public class ArrayMapToIntExample {
public static void main(String[] args) {
String[] numberStrings = {"1", "2", "3", "4", "5"};
IntStream intStream = java.util.Arrays.stream(numberStrings)
.mapToInt(Integer::parseInt);
intStream.forEach(System.out::println);
}
}
在这个例子中,我们首先有一个包含字符串数字的数组。通过 Arrays.stream
方法将数组转换为流,然后使用 mapToInt
方法将每个字符串映射为对应的 int
值,生成一个 IntStream
,并打印出流中的每个 int
值。
常见实践
计算总和
使用 mapToInt
结合 sum
方法可以很方便地计算流中元素的总和。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
class Product {
private int price;
public Product(int price) {
this.price = price;
}
public int getPrice() {
return price;
}
}
public class SumExample {
public static void main(String[] args) {
List<Product> products = new ArrayList<>();
products.add(new Product(10));
products.add(new Product(20));
products.add(new Product(30));
int totalPrice = products.stream()
.mapToInt(Product::getPrice)
.sum();
System.out.println("Total price: " + totalPrice);
}
}
在这个例子中,我们有一个 Product
类,每个 Product
对象有一个 price
属性。通过 mapToInt
将每个产品的价格映射为 int
流,然后使用 sum
方法计算出所有产品价格的总和。
获取最大值
使用 mapToInt
结合 max
方法可以获取流中元素的最大值。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
class Student {
private int score;
public Student(int score) {
this.score = score;
}
public int getScore() {
return score;
}
}
public class MaxExample {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(85));
students.add(new Student(90));
students.add(new Student(95));
int maxScore = students.stream()
.mapToInt(Student::getScore)
.max()
.orElse(0);
System.out.println("Max score: " + maxScore);
}
}
这里我们有一个 Student
类,每个 Student
对象有一个 score
属性。通过 mapToInt
将学生的分数映射为 int
流,然后使用 max
方法获取最高分。由于 max
方法返回一个 OptionalInt
,我们使用 orElse
方法在流为空时返回一个默认值 0
。
获取平均值
使用 mapToInt
结合 average
方法可以获取流中元素的平均值。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
class Employee {
private int salary;
public Employee(int salary) {
this.salary = salary;
}
public int getSalary() {
return salary;
}
}
public class AverageExample {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(5000));
employees.add(new Employee(6000));
employees.add(new Employee(7000));
double averageSalary = employees.stream()
.mapToInt(Employee::getSalary)
.average()
.orElse(0);
System.out.println("Average salary: " + averageSalary);
}
}
在这个例子中,我们有一个 Employee
类,每个 Employee
对象有一个 salary
属性。通过 mapToInt
将员工的工资映射为 int
流,然后使用 average
方法获取平均工资。同样,由于 average
方法返回一个 OptionalDouble
,我们使用 orElse
方法在流为空时返回一个默认值 0
。
最佳实践
避免装箱和拆箱
mapToInt
方法的一个重要优势是避免了不必要的装箱和拆箱操作。如果使用普通的 Stream<Integer>
,在进行数值计算时会频繁地进行装箱(将 int
转换为 Integer
)和拆箱(将 Integer
转换为 int
),这会带来一定的性能开销。使用 mapToInt
直接生成 IntStream
,可以避免这种性能损耗,提高程序的执行效率。
结合其他 Stream 操作
mapToInt
可以与其他 Stream 操作,如 filter
、sorted
等结合使用,以实现更复杂的数据处理逻辑。例如,我们可以先过滤出满足条件的元素,再将其映射为 int
流进行聚合操作。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
class Fruit {
private String name;
private int price;
public Fruit(String name, int price) {
this.name = name;
this.price = price;
}
public int getPrice() {
return price;
}
}
public class ComplexOperationExample {
public static void main(String[] args) {
List<Fruit> fruits = new ArrayList<>();
fruits.add(new Fruit("Apple", 10));
fruits.add(new Fruit("Banana", 5));
fruits.add(new Fruit("Orange", 8));
int totalPriceOfExpensiveFruits = fruits.stream()
.filter(fruit -> fruit.getPrice() > 7)
.mapToInt(Fruit::getPrice)
.sum();
System.out.println("Total price of expensive fruits: " + totalPriceOfExpensiveFruits);
}
}
在这个例子中,我们首先过滤出价格大于 7 的水果,然后将这些水果的价格映射为 int
流,最后计算出这些水果的总价格。
小结
mapToInt
是 Java Stream API 中一个非常实用的方法,它能够将流中的元素方便地映射为 int
类型的值,进而进行各种聚合操作。通过避免装箱和拆箱以及结合其他 Stream 操作,我们可以更加高效地处理数据。希望通过本文的介绍,你对 mapToInt
的使用有了更深入的理解,并能在实际项目中灵活运用。