Java 8 Streams:为什么mapToInt需要Integer::parseInt作为参数?

问题描述 投票:0回答:5

我试图理解下一个示例中的一些内容:

    Stream.of("a1", "a2", "a3")
            .map(s -> s.substring(1))
            .mapToInt(Integer::parseInt)
            .max()

     . (etc.)

为什么mapToInt需要

    Integer::parseInt 

作为参数?难道不应该是隐含的吗?这个参数是不是多余了?

java java-8 java-stream
5个回答
2
投票

区分调用

Stream#mapToInt(ToIntFunction)
的作用和
ToIntFunction
参数的作用非常重要。

  • mapToInt
    的调用是流将要做的什么(即将元素映射到
    int
    )。
  • ToIntFunction
    参数是如何流将每个元素映射到
    int

他们是否可以包含一个无参数

mapToInt
方法,隐式地将
String
解析为
int
?是的,但是 看看它对于
Stream#sorted()
的效果有多好,而且这种情况远不像无参数
mapToInt
方法那样任意或模糊。

无参数

sorted
方法假设元素是
Comparable
,这是 Java 中一个基本的、标准化的、广泛使用的接口——任何类都可以实现该接口(而只有一个类可以是
String
) 。因此,虽然该方法不是类型安全的,但可以认为用例足够常见以证明其存在的合理性。

但是,假设元素是

mapToInt
并将其内容解析为
String
的无参数
int
方法是一个非常具体的用例。为什么这样一个通用的 API 会提供这样一个特定的操作?这将是一个完全武断的决定,没有合理的理由。例如,为什么不将每个
String
映射到其
length
呢?为什么
String
被特殊处理而不是其他类型?因此,该方法接受一个
ToIntFunction
参数,该参数描述了 如何 根据具体情况将元素映射到
int


注意到

Integer::parseInt
是一个方法引用可能会有所帮助,它是一个简单的lambda表达式的简写。两者都是功能接口的实现,这比使用匿名类更简洁。换句话说,您正在创建一个新的
ToIntFunction
实例并将其作为参数传递。

以下所有内容在功能上都是等效的:

// method reference
stream.mapToInt(Integer::parseInt)

// lambda expression
stream.mapToInt((String value) -> Integer.parseInt(value)) // explicit parameter types
stream.mapToInt(value -> Integer.parseInt(value))          // implicit parameter types

// anonymous class
stream.mapToInt(new ToIntFunction<>() {

    @Override
    public int applyAsInt(String value) {
        return Integer.parseInt(value);
    }

})

其中

stream
Stream<String>


1
投票

您正在执行的操作如下:

Stream.of("a1", "a2", "a3")           //step1
        .map(s -> s.substring(1))     //step2
        .mapToInt(Integer::parseInt)  //step3
        .max()

您定义一个字符串流(在步骤 1 中),然后将其中的每个字符串丢弃并丢弃其中的 1 个字符,留下“1”、“2”和“3”的流,(步骤 2)但请注意,这些仍然是字符串对象... 然后将其转换为整数,因此您需要为“mapToInt”提供一个“函数”,该函数接受字符串作为参数并返回整数(步骤3)

这是在 Integer 类中定义的:

https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#parseInt(java.lang.String)

你当然可以编写并传递你自己的函数......但为什么要重新发明轮子呢? :)


1
投票

substring
返回字符串而不是整数。
mapToInt
将对象流(在本例中为字符串)转换为
IntStream
int 基元。但是它不知道如何进行映射,您需要为其提供一个函数,在您的情况下是
parseInt


0
投票

实际上,读完这里的友善答案后我明白了 1.我的问题不够清楚。 2.答案...

那么,

  1. 我真正的意思是 - 将 Integer::parseInt 作为参数传递给 mapToInt 不是多余的吗?因为我觉得mapToInt准确地描述了该方法的目的 - 将对象映射到int,并且添加parseInt是不必要的,因为它实际上是相同的 - 将对象解析为int...

  2. 但是后来我也尝试传递 Integer:valueOf 并且它也被接受了 - 所以我明白有几个选项可以传递给 mapToInt,这回答了我的问题...


0
投票

1)mapToInt 函数的主要目的是将当前流转换为 Intstream,在此基础上可以执行其他 Integer 操作,如 sum、Min、max 等

  1. 它是泛型,你永远无法预测输入是什么,在你的情况下它是 String,它可能是 double 、long 或其他东西。 开发人员负责显式转换。

  2. 您可以编写自己的函数,在本例中是 function,它只不过是作为 mapToInt func 的参数的 ToIntFunction。 您可以重写自己的功能接口,例如 function ,但这里您还需要在函数 applyAsInt 内部执行 parseInt ,但这将是一项一次性工作,您可以在进行某些其他类似调用时重用。

© www.soinside.com 2019 - 2024. All rights reserved.