Java8 原始类型Stream

By | 11月 24, 2016

原始类型Stream

将基本类型(如int, double等)封装成对象,显然是一个低效的做法,Stream API 提供了IntStream,LongStream和DoubleStream来直接存储原始类型值。String类型除外,它只能用Stream<String>来处理。下面是原始类型和对应Stream的映射表。

原始数据类型

对应的Stream

String

Stream<String>

short, char, byte, boolean和int

IntStream

Long

LongStream

Double

DoubleStream

注意:shrot, char, byte和boolean,没有专门的Stream,需要时用IntStream。float也没有专门的Stream,需要时使用DoubleStream。

创建原始类型Stream

of()方法指定元素创建。

IntStream intStream = IntStream.of(1, 2, 3);
LongStream longStream = LongStream.of(4, 5, 6);
DoubleStream doubleStream = DoubleStream.of(0.1, 0.2, 0.3);

short, char, byte可以直接构造成IntStream,folat可以直接构造成DoubleStream,但是boolean类型不能直接构造成IntStream,要手动转换一下。

IntStream charStream = IntStream.of('A', 'B');
IntStream byteStream = IntStream.of((byte) 1, (byte) 2);
IntStream shortStream = IntStream.of((short) 1, (short) 2 );
DoubleStream floatStream = DoubleStream.of((float) 0.1, (float) 0.2);

// Boolean value cannot automatically be casted to integer.
// (Compile fail) IntStream.of(true, false);<br />
IntStream booleanStream = Stream.of(true, false).mapToInt(b -> b ? 1 : 0);

从数组创建原始类型Stream,数组是什么类型,创建的就是什么类型的Stream。Arrays.Stream()方法,只接受int, long, double和对象类型的数组。传入short, char, byte, boolean和float类型的数组,编译不过。

int[] nums = {1, 2, 3};
IntStream numStream = Arrays.stream(nums);

普通Stream转换成原始类型Stream。

class Book {
  private long id;
  private int pages;
  private double price;

  // Getter and setter
}

Stream<Book> books = ...
LongStream idStream = books.mapToLong(book -> book.getId());
IntStream pagesStream = books.mapToInt(book -> book.getPages());
DoubleStream priceStream = books.mapToDouble(book -> book.getPrice());

IntStream和LongStream,拥有静态方法range()和rangeClosed(),用来产生步进为1的整数范围。

IntStream zeroToNine = IntStream.range(0, 10); //Exclude 10
IntStream zeroToTen = IntStream.rangeClosed(0, 10); //Include 10

Random类提供了ints, longs和doubles方法,来生成随机数的原始类型流。下面是ints用法,longs和doubles用法相同。

Random random = new Random();
// Infinite
IntStream ints1 = random.ints();
// Indicate size (5).
IntStream ints2 = random.ints(5);
// Indicate range [5, 100). 5 is inclusive, 100 is exclusive.
IntStream ints3 = random.ints(5, 100);
// Indicate size (20) and range [0, 100).
IntStream ints4 = random.ints(20, 0, 100);

Optional结果

原始类型Stream,产生Optional的方法会返回一个OptionalInt,OptionalLong或者OptionalDouble。它们没有get()方法,对应的是getAsInt、getAsLong和getAsDouble。

OptionalDouble value = random.doubles(5, 0.01, 1.0).findFirst();
double doubleValue = value.getAsDouble();

对原始Stream,进行数学统计

方法count,sum,average,max和min会返回元素个数,总和,平均值,最大值和最小值。这种统计方法,只能使用一个,因为任何操作都会把Stream关闭掉。

IntStream nums = random.ints(10, 0, 100);
OptionalInt max = nums.max();
//Cannot apply min() again.
//OptionalInt min = nums.min();

如果想同时统计Stream的最大值、最小值、平均值等,改怎么办?

summaryStatistics()方法,会产生一个IntSummaryStatistics,LongSummaryStatistics或者DoubleSummaryStatistics对象,可以同时获得元素个数、总和、平均值、最大值和最小值。

IntStream nums = random.ints(10, 0, 100);
IntSummaryStatistics statistics = nums.summaryStatistics();
long count = statistics.getCount();
long sum = statistics.getSum();
double average = statistics.getAverage();
int max = statistics.getMax();
int min = statistics.getMin();

其它

1. 原始类型Stream的toArray()方法,会返回原始类型的数组,不用传入数组构造器转型。

2. boxed()方法,将原始类型Stream转换成对象Stream

Stream<Integer> boxed = IntStream.of(1, 2, 3).boxed();