ZetCode

Java Stream mapToObj

最后修改于 2025 年 5 月 25 日

本文探讨了 Java Stream 的 mapToObj 方法,该方法可以将原始类型流 (IntStreamLongStreamDoubleStream) 转换为对象流。通过将数值数据转换为引用类型,mapToObj 增强了流操作的灵活性,使其更容易应用复杂的转换和对象操作。

mapToObj 方法是一种专门为原始类型流设计的中间流操作。它将每个原始类型值转换为一个对象,从而实现原始类型和基于引用的数据结构之间的无缝转换。此方法与 mapToIntmapToLongmapToDouble 对应,确保了 Java 函数式编程范例中不同数据表示形式之间的兼容性。

使用 mapToObj,开发人员可以利用面向对象的特性,例如存储额外的元数据、将复杂的逻辑应用于单个元素以及将原始类型值集成到更结构化的模型中。这使其成为高效处理数值数据同时保持 Java Stream 优势的宝贵工具。

mapToObj 基本语法

mapToObj 方法允许你将流中的每个原始类型值转换为一个对象,从而实现原始类型流和对象流之间灵活的数据转换。

// IntStream
<U> Stream<U> mapToObj(IntFunction<? extends U> mapper)

// LongStream
<U> Stream<U> mapToObj(LongFunction<? extends U> mapper)

// DoubleStream
<U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper)

mapper 函数将每个原始类型值转换为 U 类型的对象。

将数字转换为字符串

你可以通过将每个数字映射到描述性字符串表示形式,轻松地将原始数字流转换为字符串流。

Main.java
void main() {

    IntStream.rangeClosed(1, 5)
             .mapToObj(i -> "Number " + i)
             .forEach(System.out::println);
}

此示例将一系列整数转换为描述性字符串。lambda 表达式 i -> "Number " + i 充当映射函数。

$ java Main.java
Number 1
Number 2
Number 3
Number 4
Number 5

创建自定义对象

原始类型值可以映射到自定义对象,从而允许你直接从原始类型流构建更复杂的数据结构。

Main.java
record Square(int side, int area) {}

void main() {

    IntStream.rangeClosed(1, 5)
             .mapToObj(side -> new Square(side, side * side))
             .forEach(System.out::println);
}

此示例从整数值创建 Square 对象,计算面积作为映射过程的一部分。

$ java Main.java
Square[side=1, area=1]
Square[side=2, area=4]
Square[side=3, area=9]
Square[side=4, area=16]
Square[side=5, area=25]

与其他操作结合使用

mapToObj 方法可以与其他流操作结合使用,以创建强大而富有表现力的数据处理管道。

Main.java
void main() {

    IntStream.range(0, 100)
             .filter(n -> n % 15 == 0)
             .mapToObj(n -> n + " is divisible by 15")
             .limit(5)
             .forEach(System.out::println);
}

此示例筛选出能被 15 整除的数字,将它们转换为描述性字符串,限制为 5 个结果,然后打印它们。

$ java Main.java
0 is divisible by 15
15 is divisible by 15
30 is divisible by 15
45 is divisible by 15
60 is divisible by 15

使用 DoubleStream

你可以在 DoubleStream 上使用 mapToObj 将 double 值转换为格式化的字符串或其他对象类型,根据需要。

Main.java
void main() {

    DoubleStream.of(1.5, 2.3, 3.7, 4.1)
               .mapToObj(d -> String.format("Value: %.2f", d))
               .forEach(System.out::println);
}

此示例使用 DoubleStream 上的 mapToObj 将 double 值格式化为带有 2 位小数的字符串。

$ java Main.java
Value: 1.50
Value: 2.30
Value: 3.70
Value: 4.10

装箱原始类型值

原始类型值可以被装箱到它们对应的包装类中,例如将 IntStream 转换为 Integer 对象的 Stream。

Main.java
void main() {

    List<Integer> numbers = IntStream.rangeClosed(1, 5)
                                   .mapToObj(Integer::valueOf) // can be replaced with boxed()
                                   .toList();
    
    System.out.println("Collected numbers: " + numbers);
}

此示例通过将每个原始 int 装箱到 Integer 对象,将 IntStream 转换为 List<Integer>。

$ java Main.java
Collected numbers: [1, 2, 3, 4, 5]

构建复杂对象

你可以通过将每个值映射到自定义类的新实例,从原始类型值创建复杂的对象层次结构。

Main.java
class Circle {
    double radius;
    double area;
    
    Circle(double radius) {
        this.radius = radius;
        this.area = Math.PI * radius * radius;
    }
    
    @Override public String toString() {
        return String.format("Circle[r=%.1f, a=%.2f]", radius, area);
    }
}

void main() {

    IntStream.rangeClosed(1, 5)
             .mapToObj(Circle::new)
             .forEach(System.out::println);
}

此示例使用整数半径创建具有计算面积的 Circle 对象。

$ java Main.java
Circle[r=1.0, a=3.14]
Circle[r=2.0, a=12.57]
Circle[r=3.0, a=28.27]
Circle[r=4.0, a=50.27]
Circle[r=5.0, a=78.54]

与 flatMap 结合使用

通过将 mapToObjflatMap 结合使用,你可以执行高级转换并将嵌套流展平为单个对象流。

Main.java
void main() {

    IntStream.rangeClosed(1, 3)
             .mapToObj(i -> IntStream.rangeClosed(1, i)
                                    .mapToObj(j -> i + "x" + j + "=" + (i*j)))
             .flatMap(s -> s)
             .forEach(System.out::println);
}

此示例通过首先为每个数字创建字符串流,然后将它们展平为单个流来生成乘法表。

$ java Main.java
1x1=1
2x1=2
2x2=4
3x1=3
3x2=6
3x3=9

来源

Java Stream mapToObj 文档

在本文中,我们探讨了 Java Stream 的 mapToObj 方法。它充当原始类型流和对象流之间的桥梁,能够在保持流处理效率的同时实现灵活的数据转换。

作者

我的名字是 Jan Bodnar,我是一位热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。到目前为止,我已撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有Java教程