Primitive Type Streams in Java 8 – Java 8中的原始类型流

最后修改: 2017年 12月 22日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

The Stream API was one of the key features added in Java 8.

流API是Java 8中增加的关键功能之一。

Briefly, the API allows us to process collections and other sequences of elements – conveniently and more efficiently – by providing a declarative API.

简而言之,该API允许我们处理集合和其他元素序列–方便和更有效地–通过提供一个声明式的API。

2. Primitive Streams

2.原始流

Streams primarily work with collections of objects and not primitive types.

流主要与对象的集合而不是原始类型一起工作。

Fortunately, to provide a way to work with the three most used primitive types – int, long and double – the standard library includes three primitive-specialized implementations: IntStream, LongStream, and DoubleStream.

幸运的是,为了提供一种方法来处理三种最常用的原始类型–int、longdouble–标准库包括三种原始类型的专门实现。IntStreamLongStreamDoubleStream

Primitive streams are limited mainly because of boxing overhead and because creating specialized streams for other primitives isn’t’ that useful in many cases.

原始流是有限的,主要是因为装箱的开销,而且在许多情况下为其他原始流创建专门的流并不那么有用。

3. Arithmetic Operations

3.算术运算

Let’s start with a few interesting methods for heavily used arithmetic operations such as min, max, sum, and average:

让我们从一些有趣的方法开始,这些方法用于大量使用的算术运算,如min, max, sum, 和average:

int[] integers = new int[] {20, 98, 12, 7, 35};
int min = Arrays.stream(integers)
  .min()
  .getAsInt(); // returns 7

Let’s now step through the code snippet above to understand what’s going on.

现在让我们通过上面的代码片断来了解发生了什么事。

We created our IntStream by using java.util.Arrays.stream(int[]) and then used the min() method to get the lowest integer as java.util.OptionalInt and finally called getAsInt() to get the int value.

我们通过使用java.util.Arrays.stream(int[])创建了我们的IntStream,然后使用min()方法来获取最低的整数作为java.util.OptionalInt,最后调用getAsInt()来获取int值。

Another way to create an IntStream is using IntStream.of(int…). The max() method will return the greatest integer:

创建IntStream的另一种方法是使用IntStream.of(int…)max()方法将返回最大的整数。

int max = IntStream.of(20, 98, 12, 7, 35)
  .max()
  .getAsInt(); // returns 98

Next – to get the sum of integers we just call the sum() method and we don’t need to use getAsInt() since it already returns the result as an int value:

接下来–为了得到整数的总和,我们只需调用sum()方法,我们不需要使用getAsInt(),因为它已经将结果作为一个int值返回。

int sum = IntStream.of(20, 98, 12, 7, 35).sum(); // returns 172

We invoke the average() method to get the average of integer values and as we can see, we should use getAsDouble() as it returns a value of type double.

我们调用average()方法来获取整数值的平均值,正如我们所看到的,我们应该使用getAsDouble(),因为它返回一个double类型的值。

double avg = IntStream.of(20, 98, 12, 7, 35)
  .average()
  .getAsDouble(); // returns 34.4

4. Range

4.范围

We can also create an IntStream based on a range:

我们还可以根据一个范围创建一个IntStream

int sum = IntStream.range(1, 10)
  .sum(); // returns 45
int sum = IntStream.rangeClosed(1, 10)
  .sum(); // returns 55

As the code snippet above shows there are two ways to create a range of integer values range() and rangeClosed().

正如上面的代码片段所示,有两种方法来创建一个整数值的范围range()rangeClosed()

The difference is that the end of range() is exclusive while it is inclusive in rangeClosed().

不同的是,range()的结束是排他性的,而在rangeClosed()中是包容性的。

Range methods are only available for IntStream and LongStream.

范围方法只适用于IntStreamLongStream

We can use range as a fancy form of a for-each loop:

我们可以用range作为for-each循环的一种花式形式。

IntStream.rangeClosed(1, 5)
  .forEach(System.out::println);

What’s good at using them as a for-each loop replacement is that we can also take advantage of the parallel execution:

使用它们作为for-each循环的替代品的好处是,我们还可以利用并行执行的优势。

IntStream.rangeClosed(1, 5)
  .parallel()
  .forEach(System.out::println);

As helpful as these fancy loops are it’s still better to use the traditional for-loops instead of the functional one for simple iterations because of simplicity, readability, and performance in some cases.

尽管这些花哨的循环很有帮助,但对于简单的迭代来说,使用传统的for-loops而不是函数式的,因为在某些情况下,简单性、可读性和性能更好。

5. Boxing and Unboxing

5.拳击和开箱

There’re times when we need to convert primitive values to their wrapper equivalents.

有些时候,我们需要将原始值转换为它们的封装等价物。

In those cases, we can use the boxed() method:

在这些情况下,我们可以使用boxed() 方法。

List<Integer> evenInts = IntStream.rangeClosed(1, 10)
  .filter(i -> i % 2 == 0)
  .boxed()
  .collect(Collectors.toList());

We can also convert from the wrapper class stream to the primitive stream:

我们还可以从包装类流转换到原始流。

// returns 78
int sum = Arrays.asList(33,45)
  .stream()
  .mapToInt(i -> i)
  .sum();

We can always use mapToXxx and flatMapToXxx methods to create primitive streams.

我们总是可以使用mapToXxxflatMapToXxx方法来创建原始流。

6. Conclusion

6.结论

Java Streams is a very powerful addition to the language. We’ve barely scratched the surface of primitive streams here, but, as you can already use them to be productive.

Java流是对语言的一个非常强大的补充。我们在这里几乎没有触及原始流的表面,但是,由于你已经可以利用它们来提高工作效率。

And, as always, code samples can be found over on GitHub.

而且,像往常一样,可以在GitHub上找到代码样本