int calories = menu.stream().map(Dish::getCalories).reduce(0, Integer::sum);
这段代码的问题是,它有一个暗含的 装箱成本。每个Integer都必须拆箱成一个原始类型,再进行求和
Java 8引入了三个原始类型特化流接口来解决这个问题:IntStream
、DoubleStream
和LongStream
,分别将流中的元素特化为int、long和double,从而避免了暗含的装箱成本。这些特化的原因并不在于流的复杂性,而是装箱造成的复杂性——即类似int和Integer之间的效率差异。
mapToInt
、mapToDouble
、mapToLong
sum
、max
、min
、average
int calories = menu.stream() ←─返回一个Stream<Dish>
.mapToInt(Dish::getCalories) ←─返回一个IntStream
.sum();
请注意,如果流是空的,sum默认返回0。
IntStream还支持其他的方便方法,如max、min、average等。
# 求和
int[] ints = new int[]{1, 2, 3};
int sum = Arrays.stream(ints).sum(); // 1+2+3=6
# 求前3项和
int sum1 = Stream.of(1, 2, 2, 4, 4).mapToInt(Integer::intValue).limit(3).sum(); // 1+2+2=5
# 求3到5项的加和
int sum2 = Stream.of(1, 2, 2, 4, 4).mapToInt(Integer::intValue).skip(2).limit(3).sum(); // 2+4+4=10
int[] ints = new int[]{1, 2, 3};
# 求最大值
int max = Arrays.stream(ints).max().getAsInt(); // 3
# 最小值
int min = Arrays.stream(ints).min().getAsInt(); // 1
# 平均值
double average = Arrays.stream(ints).average().getAsDouble(); // 2.0
boxed
IntStream intStream = menu.stream().mapToInt(Dish::getCalories); ←─将Stream 转换为数值流
Stream<Integer> stream = intStream.boxed(); ←─将数值流转换为Stream
OptionalInt
、OptionalDouble
、OptionalLong
OptionalInt maxCalories = menu.stream().mapToInt(Dish::getCalories).max();
nt max = maxCalories.orElse(1); ←─如果没有最大值的话,显式提供一个默认最大值
rangeClosed
,range
)#
IntStream evenNumbers = IntStream.rangeClosed(1, 100) ←表示范围[1, 100]
.filter(n -> n % 2 == 0); ←一个从1到100的偶数流
System.out.println(evenNumbers.count()); ←从1 到100 有50个偶数
IntStream evenNumbers = IntStream.range(1, 100) ←表示范围[1, 100)
.filter(n -> n % 2 == 0);
System.out.println(evenNumbers.count()); ←从1 到99 有49个偶数
Stream<int[]> pythagoreanTriples =
IntStream.rangeClosed(1, 100).boxed()
.flatMap(a -> IntStream.rangeClosed(a, 100)
.filter(b -> Math.sqrt(a*a + b*b) % 1 == 0)
.mapToObj(b ->new int[]{a, b, (int)Math.sqrt(a * a + b * b)}));
Stream<double[]> pythagoreanTriples2 =
IntStream.rangeClosed(1, 100).boxed()
.flatMap(a -> IntStream.rangeClosed(a, 100)
.mapToObj(b -> new double[]{a, b, Math.sqrt(a*a + b*b)}) ←─产生三元数
.filter(t -> t[2] % 1 == 0)); ←─元组中的第三个元素必须是整数
pythagoreanTriples.limit(5).forEach(t ->System.out.println(t[0] + ", " + t[1] + ", " + t[2]));
a%1==0 → a是整数
-----------------------------------------------------------------------------读书笔记摘自 书名:Java 8实战 作者:[英] Raoul-Gabriel Urma [意] Mario Fusco [英] Alan M 第 5 章 使用流 5.6 数值流