java8 数值流介绍

引入背景

int calories = menu.stream().map(Dish::getCalories).reduce(0, Integer::sum);

这段代码的问题是,它有一个暗含的 装箱成本。每个Integer都必须拆箱成一个原始类型,再进行求和

原始类型流特化

Java 8引入了三个原始类型特化流接口来解决这个问题:IntStreamDoubleStreamLongStream,分别将流中的元素特化为int、long和double,从而避免了暗含的装箱成本。这些特化的原因并不在于流的复杂性,而是装箱造成的复杂性——即类似int和Integer之间的效率差异。

1. 映射到数值流 mapToIntmapToDoublemapToLong

summaxminaverage

int calories = menu.stream()    ←─返回一个Stream<Dish>
                   .mapToInt(Dish::getCalories)    ←─返回一个IntStream
                   .sum();
                   
请注意,如果流是空的,sum默认返回0IntStream还支持其他的方便方法,如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

统计符合条件的个数 count

# 统计符合条件的个数
 long count = Arrays.stream("a,b,c,a".split(",")).filter("a"::equals).count(); // 2

2. 转换回对象流 boxed

IntStream intStream = menu.stream().mapToInt(Dish::getCalories);    ←─将Stream 转换为数值流

Stream<Integer> stream = intStream.boxed();    ←─将数值流转换为Stream

3. 默认值OptionalInt OptionalIntOptionalDoubleOptionalLong

OptionalInt maxCalories = menu.stream().mapToInt(Dish::getCalories).max();

nt max = maxCalories.orElse(1);    ←─如果没有最大值的话,显式提供一个默认最大值

数值范围(rangeClosedrange

# 
IntStream evenNumbers = IntStream.rangeClosed(1, 100)    ←表示范围[1, 100]
                                 .filter(n -> n % 2 == 0);    ←一个从1100的偶数流
                                 
System.out.println(evenNumbers.count());    ←从110050个偶数


IntStream evenNumbers = IntStream.range(1, 100)       ←表示范围[1, 100)
                                 .filter(n -> n % 2 == 0); 
                                 
System.out.println(evenNumbers.count());    ←从19949个偶数

数值流应用:勾股数

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 数值流

你可能感兴趣的:(JAVA8,读书笔记,python,开发语言)