在下一个示例中,我试图了解一些内容:
Stream.of("a1", "a2", "a3")
.map(s -> s.substring(1))
.mapToInt(Integer::parseInt)
.max()
. (etc.)
为什么mapToInt需要
Integer::parseInt
作为参数?它不应该是隐式的吗?这个参数不是多余的吗?
谢谢!
答案 0 :(得分:2)
这不是多余的。您需要说一下如何将字符串“ 1”转换(例如)为整数1。
(我想您可能会说无参数的mapToLong
方法会很方便,但是设计人员没有在API中包含一个。)
我想您可能还会问为什么要去进行显式整数转换的麻烦。
如果您尝试将Stream::max
应用于数字表示的字符串流,则会得到词法上的最大值,而不是数字上的最大值。例如,“ 9”大于“ 11”。
请注意,Stream::max
方法没有没有参数的重载。您需要提供一个比较器;例如
Stream.of("a1", "a2", "a3")
.map(s -> s.substring(1))
.max(compareAsIntegers)
其中
Comparator<String> compareAsIntegers = new Comparator<String>() {
public int compare (String s1, String s2) {
return Integer.compare(Integer.parseInt(s1),
Integer.parseInt(s2));
}
}
答案 1 :(得分:1)
substring
返回的字符串不是整数。
mapToInt
将对象流(在本例中为Strings)转换为int原语的IntStream
。但是,它不知道如何进行映射,您需要为其提供一个函数,在您的情况下为parseInt
。
答案 2 :(得分: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)
您可以肯定地编写并传递自己的函数...但是为什么要重新发明轮子呢? :)
答案 3 :(得分:1)
重要的是要区分调用Stream#mapToInt(ToIntFunction)
和参数ToIntFunction
的作用。
mapToInt
的调用是流将要做什么(即,将元素映射到int
)。ToIntFunction
参数是如何如何将流映射到每个元素到int
。他们是否可以包含一个无参数的mapToInt
方法,该方法将String
隐式地解析为int
s?是的,但是look at how well that works for Stream#sorted()
—这种情况远比无参数的mapToInt
方法更加随意或模棱两可。
no-arg sorted
方法假定元素为Comparable
,这是Java中基本的,标准化的且广泛使用的接口-任何类都可以实现该接口(而只有一个类可以实现是String
)。因此,尽管该方法不是类型安全的,但可以认为用例足够普遍,足以证明其存在的合理性。
但是,无参数的mapToInt
方法假定元素是String
并将其内容解析为int
是一个非常特定的用例。为什么这样的通用API提供这样的特定操作?没有合理的理由,这将是一个完全武断的决定。例如,为什么不将每个String
映射到其length
?为什么String
被特别处理而不是其他一些类型?因此,该方法接受一个ToIntFunction
参数,该参数描述了如何视情况将元素映射到int
的情况。
请注意,Integer::parseInt
是method reference,这是琐碎的lambda expression的缩写。两者都是functional interface的实现,与使用anonymous class相比,该选项的详细程度较低。换句话说,您正在创建一个新的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>
的地方。
答案 4 :(得分:0)
实际上,在阅读了这里的善意答案后,我明白了 1.我的问题还不够清楚。 2.答案...
所以
我真正的意思是-是否没有将Integer :: parseInt用作mapToInt冗余的参数?因为我觉得mapToInt恰好描述了该方法的目的-将对象映射到int,并且添加parseInt是不必要的,因为它实际上是相同的-将对象解析为int ...
但是后来我尝试也传递Integer:valueOf,它也被接受-因此我知道有几个选项可以传递给mapToInt,这回答了我的问题...
< / li>答案 5 :(得分:0)
1)mapToInt 函数的主要目的是将当前流转换为 Intstream,在 Intstream 上可以执行其他 Integer 操作,如 sum、Min、max 等。
它是泛型,你永远无法预测输入是什么,在你的情况下它是字符串,它可能是 double ,long 或其他东西。 由开发人员来处理显式转换。
您可以编写自己的函数,在本例中它是 function