IntStream.boxed() 与 for 循环 | 表现

piy*_*yal 3 java java-8 java-stream

我正在编写一段代码,其中有一个 String[] 和一个接受这个 String[] 并返回 Byte[] 的方法,该方法维护字符串-字节对,其中很少有 Byte 可以为空。最终,我必须转换 Byte 并从 String[] 中获取 key 作为 string 和 value 作为转换的返回的映射。这就是我在 Java 8 流中实现相同的方式:

IntStream.range(0, productReferences.length)
            .filter(index -> (null!= productsPrice[index])).boxed()
            .collect(Collectors.toMap(position -> productReferences[position],
                    position ->callSomeMethod(productsPrice[position])));
Run Code Online (Sandbox Code Playgroud)

其中 productReference 是 String[] 和 productsPrice[] 是 Byte[] 数组。

现在的问题是 IntStream.boxed() 方法。在内部,它将 int 装箱为 Integer 以便它返回一个 Stream,我认为这是一个成本更高的操作。

其他方法是使用 java for 循环

    for(int i=0;i<productReferences.length; i++){
    if (productsPrice[index]==null) continue;
    //other code
}
Run Code Online (Sandbox Code Playgroud)

处理这种情况的最佳方法是什么?我理解创建 IntStream 的原因,但是如果我实际上可以在没有 boxed() 方法的 collect 方法中使用索引从而避免装箱?

Tun*_*aki 5

您可以使用collect您拥有的操作,IntStream而不是将其装箱到Stream<Integer>.

IntStream.range(0, productReferences.length)
         .filter(index -> productsPrice[index] != null)
         .collect(
            HashMap::new,
            (m, i) -> m.put(productReferences[i], callSomeMethod(productsPrice[i])),
            Map::putAll
         );
Run Code Online (Sandbox Code Playgroud)

这不会将每个索引都装箱到一个中,Integer因为收集器的使用者部分需要一个ObjIntConsumer; 所以i在上面的代码中是一个int. 正如 Holger 所指出的,初始代码 usingCollectors.toMap会在重复键的情况下抛出异常,当此版本会覆盖该值时。

您仍然需要根据您的真实数据对这两个解决方案进行基准测试,看看这是否会带来改进。

  • 这可能是潜在的性能改进的假设是 `IntStream` 存在的原因。但需要注意的是,存在语义差异。`toMap` 会抛出一个异常,如果有重复的键,而这个变体会默默地覆盖。顺便说一下,这个值应该是`callSomeMethod(productsPrice[position])`,而不是`productsPrice[position]`。 (2认同)