Java8 教程

Java8 原始类型流

到目前为止,我们已经将 Integer、Long 收集到了一个 Stream<Integer>、Stream<Long> 的流中,不过将每个整数包装成相应对象显然是一个低效的做法,对于其他原始类型 double、float、long、short、char、byte 及 boolean 也是一样。

为此,Java8 Stream API 提供了 IntStream、LongStream 和 DoubleStream 等类型,专门用来直接存储原始类型值,不必使用包装。

如果你想要存储 short、char、byte 和 boolean 类型的值,请使用 IntStream;而如果要存储 float 类型的值,请使用 DoubleStream。这是因为 Stream API 的设计者们认为,不需要为其他 5 种原始类型都添加对应的专门类型。

要创建一个 IntStream,你可以调用 Intstream.of 和 Arrays.stream 方法:

IntStream intStream = IntStream.of(1, 2, 3);
intStream.max().ifPresent(System.out::println);
//输出:3

Arrays.stream(new int[]{1, 2, 3}).max().ifPresent(System.out::println);
//输出:3

对于对象流,你还可以使用静态的生成和迭代方法。除此之外,IntStream 和 LongStream 还拥有静态方法 range 和 rangeclosed,用来产生步长为1的一个整数范围。例如:

IntStream zeroToNinetyNine = IntStream.range(0,100); // 不包括上限 IntStream
System.out.println("sum=" + zeroToNinetyNine.sum());//sum=4950

IntStream zeroToHundred = IntStream.rangeClosed(0,100); // 包括上限
System.out.println("sum=" + zeroToHundred.sum()); //sum=5050

CharSequence 接口有两个方法 codePoints 和 chars,可以生成包含字符 Unicode 代码的流,或者是包含 UTF-16 编码的代码单元的 IntStream。例如:

// \uD835\uDD46 是字母 ① 的 UTF-16 编码,unicode 是 U+1D546
String sentence = "\uD835\uDD46 is the set of octonions.";
IntStream codes = sentence.codePoints();
codes.forEach(e -> {
    System.out.println(e + " = " + Integer.toHexString(e) + " = " + (char) e);
});
//输出:
//120134 = 1d546 = 핆
//32 = 20 =
//105 = 69 = i
//115 = 73 = s
//32 = 20 =
//116 = 74 = t
//104 = 68 = h
//101 = 65 = e
//32 = 20 =
//115 = 73 = s
//101 = 65 = e
//116 = 74 = t
//32 = 20 =
//111 = 6f = o
//102 = 66 = f
//32 = 20 =
//111 = 6f = o
//99 = 63 = c
//116 = 74 = t
//111 = 6f = o
//110 = 6e = n
//105 = 69 = i
//111 = 6f = o
//110 = 6e = n
//115 = 73 = s
//46 = 2e = .

当你拥有一个对象流的时候,你可以通过 mapToInt、mapToLong 或者 mapToDouble 方法将它转换为一个原始类型流。例如,如果你有一个字符串流,并且希望按照它们的长度 (整型) 进行处理时,你可能会使用一个 IntStream:

List<String> list = Arrays.asList("one", "two", "three");
Stream<String> stream = list.stream();
int[] arrays = stream.mapToInt(String::length).toArray();
System.out.println(Arrays.toString(arrays));
//输出:[3, 3, 5]

要将一个原始类型流转换为一个对象流,可以使用 boxed 方法:

List<String> list = Arrays.asList("one", "two", "three");
Stream<String> stream = list.stream();
// 得到原始类型流
IntStream intStream = stream.mapToInt(String::length);
// 将原始类型流转换为对象流
Stream<Integer> integerStream = intStream.boxed();
System.out.println(integerStream.collect(Collectors.toList()));
//输出:[3, 3, 5]

一般来说,原始类型流上的方法与在对象流上调用的方法类似,但是有以下几点显著的区别:

  • toArray 方法会返回一个原始类型的数组,如:int[]。

  • 产生 Optional 结果的方法会返回一个 OptionalInt、OptionalLong 或者 OptionalDouble 类型。这些类与 Optional 类类似,但是它们没有 get 方法,而是用对应的 getAsInt、getAsLong 和 getAsDouble 来代替。例如:

List<String> list = Arrays.asList("one", "two", "three");
        OptionalInt opt = list.stream().mapToInt(String::length).max();
        System.out.println(opt.getAsInt()); // 5
  • 方法 sum、average、max 和 min 会返回总和、平均值、最大值和最小值。在对象流中没有定义这些方法。

  • summaryStatistics 方法会产生一个 IntSummaryStatistics、LongSummaryStatistics 或者DoubleStummaryStatistics 对象,可以同时获得原始类型流的总和、平均值、最大值和最小值。例如:

List<String> list = Arrays.asList("one", "two", "three");
        Stream<String> stream = list.stream();
        // 得到原始类型流
        IntStream intStream = stream.mapToInt(String::length);
        IntSummaryStatistics statistics = intStream.summaryStatistics();
        System.out.println("avg = " + statistics.getAverage());
        System.out.println("count = " + statistics.getCount());
        System.out.println("max = " + statistics.getMax());
        System.out.println("min = " + statistics.getMin());
        System.out.println("sum = " + statistics.getSum());
        //输出:
        //avg = 3.6666666666666665
        //count = 3
        //max = 5
        //min = 3
        //sum = 11

注意:Random 类现在提供了 ints、longs 和 doubles 这些方法,用来返回包含随机数字的原始类型流。例如:

Random random = new Random();
// 生成10个 0~100 随机整数
int[] randoms = random.ints(10, 0, 100).toArray();
System.out.println(Arrays.toString(randoms));
//输出:
//[41, 73, 58, 46, 95, 3, 29, 72, 57, 48]


说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号