如何从List<Integer>获取IntStream?

65

我可以想到两种方法:

public static IntStream foo(List<Integer> list)
{
    return list.stream().mapToInt(Integer::valueOf);
}

public static IntStream bar(List<Integer> list)
{
    return list.stream().mapToInt(x -> x);
}

什么是惯用方式?也许已经有一个库函数可以完全满足我的需求了吗?


另一种可能的方法是使用flatMapToIntInstream.of - Naman
使用 Integer::valueOf 是非常低效的。我想知道这样的事情在生产代码中有多常见。我曾经看到过一些不那么严重的装箱-拆箱的例子。 - Tom Hawtin - tackline
2个回答

68

我猜(或者至少这是一种替代方案),这种方式更加高效:

public static IntStream baz(List<Integer> list)
{
    return list.stream().mapToInt(Integer::intValue);
}

由于函数Integer::intValueToIntFunction完全兼容,因为它接受一个Integer并返回一个int。不执行autoboxing

我还在寻找Function::identity的等效方法,希望编写与您的bar方法等效的方法:

public static IntStream qux(List<Integer> list)
{
    return list.stream().mapToInt(IntFunction::identity);
}

但是他们没有提供这个identity方法。不知道为什么。

3
我混淆了Integer::valueOfInteger::intValue。我提出的函数foo将列表中的整数解封装为基本类型,然后将其传递给valueOf方法进行包装,之后它又被封装成一个箱子,然后再次被解封装以放入流中 :) - fredoverflow
1
@shmosel 因为 intValue 不执行自动装箱。 - gontard
5
什么是自动装箱?在lambda版本中,x已经是一个整数(来自列表),并且“return x”将其隐式地_un_boxes转换为int,使用intValue。我怀疑差异一开始是难以察觉的,并且随着JIT的运行会变得越来越小。 - yshavit
1
@yshavit 更不用说一个身份函数也会做完全相同的事情。 - shmosel
1
@VictorZamanian - 这里没有装箱操作。值在列表中起初是Integer类型的,然后传递给了ToIntFunction.applyAsInt(T value),该函数接受一个对象并返回int类型,因此在调用它时不需要将Integer转换为T。然后,lambda函数x -> x 接受一个Integer x并将其返回,这意味着它被取消装箱以符合int返回类型。之后没有进一步的装箱或取消装箱操作。偏好使用 Integer :: intValue 的一个有效原因是不会创建额外的 lambda 函数 - 直接使用方法引用即可。 - BeeOnRope
显示剩余4条评论

7

另一种转换方式是使用Stream.flatMapToIntIntStream.of,代码如下:

public static IntStream foobar(List<Integer> list) {
    return list.stream().flatMapToInt(IntStream::of);
}

注意:在发布此贴之前,我查看了几个相关问题的链接,但是没有找到这种建议。


聪明,即使对于流也无望地低效。但是聪明。 - Tom Hawtin - tackline

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接