IntStream的用法详解

IntStream是一种特殊的Stream,用来提供对int类型数据进行相关的stream操作,下面我们一起来看下。

1生成IntStream

1.1IntStream.generate

用来生成无限个数整数对应的stream,对于需要持续获取随机值的场景可以考虑使用这种方式。

   public void testGenerate(){
        Random random=new Random();
        IntStream.generate(()->random.nextInt(1000)).limit(500).forEach(System.out::println);
    }

通过IntSupplier()->random::nextInt,生成无限个0到1000以内的整数,然后通过forEach获取。输出结果如下:

.......

296
90
46
28
66
343
207
315
530

.......

1.2IntStream.range

生成某个数字范围内的数字集合stream,range是左闭右开的,对应还有rangeClose,左闭右闭的。

  public static void testRangeAndRangeClosed(){
        System.out.println("左闭右开");
        IntStream.range(0,5).forEach(System.out::println);
        System.out.println("左闭右闭");
        IntStream.rangeClosed(0,5).forEach(System.out::println);
  }

输出如下:

左闭右开
0
1
2
3
4
左闭右闭
0
1
2
3
4
5

1.3Stream.of

使用一组给定值生成stream

public static void testOf(){
       IntStream.of(2,4,8,10).forEach(System.out::println);
}

输出如下:

2
4
8
10

1.4Stream.empty

生成不包含任何元素的空流

   public static void testEmpty(){
        int sum=IntStream.empty().sum();
        System.out.println(sum);
        IntStream.empty().forEach(System.out::println);
    }

输出如下:

img

1.5IntStream.builder

使用类似于建造者模式构建一个流,可以通过add方法添加多个元素,最后用build获取流对象。

 public static void testBuilder(){
       IntStream.builder().add(10).add(100).add(88).build().forEach(System.out::println);
    }

输出如下:

10
100
88

1.6IntStream.iterate

通过迭代函数,生成一个有序无限的Int数据流。(由于是无限流,一般都是配合limit来使用)

 public static void testIterate(){
        //参数一:seed初始值
        //参数二:IntUnaryOperator用前一个元素以生成新元素的函数
        //用limit截断,防止无限输出
        IntStream.iterate(1,x->x*4).limit(5).forEach(System.out::println);
    }

输出如下:

1
4
16
64
256

1.7IntStream.concat

和并流,使用concat方法将连个不同流合并为一个流输出

 public static void testConcat(){
        IntStream stream1=IntStream.of(12,55,10,14);
        IntStream stream2=IntStream.builder().add(10).add(8).add(15).build();
        IntStream.concat(stream1,stream2).forEach(System.out::println);
    }

输入如下:

12
55
10
14
10
8
15

2操作Stream

2.1过滤操作filter

通过filter来过滤不需要的元素,测试和输出如下:

    public static void testFilter(){
        //将下列大于等于60的元素筛选出来,并打印在控制台
        IntStream score = IntStream.of(88, 45, 60, 99, 59, 90);

        score.filter(x->x>=60).forEach(System.out::println);

    }

88
60
99
90

2.2转换map

map用于操作当前的所有元素,已给定操作生成新值,并用新值替换旧值。测试和输出如下:

  public static void testMap(){
        IntStream.rangeClosed(20,30).map(x->x*2).forEach(System.out::println);

    }

40
42
44
46
48
50
52
54
56
58
60

2.3mapToObj

mapObj可以将元素转换为其他任意类型,具体转换类型由实现类决定,测试代码和运行结果如下:

    public static void testMapToObj(){
        //mapToObj将int类型装换为String类型,也可转换为其他类型,由lambda表达式的返回结果决定
        Stream<String> stringStream = IntStream.rangeClosed(10, 15).mapToObj(e -> String.valueOf(e));
        stringStream.forEach(v->{
            System.out.println(v+" "+v.getClass());
        });
    }

10 class java.lang.String
11 class java.lang.String
12 class java.lang.String
13 class java.lang.String
14 class java.lang.String
15 class java.lang.String

2.4mapToLong

mapToLong顾名思义,将int类型转换为Long类型,测试和运行结果如下:

    public static void testMapToLong(){
        //隐式转换,在java中int类型占4个字节,long类型8个字节,jvm会将短精度类型自动转换为长精度类型
        //或者也可以用Long包装类的valueOf方法将int类型转换为long类型
        LongStream longStream = IntStream.rangeClosed(10, 15).mapToLong(e -> e*2);
        longStream.forEach(v->{
            System.out.println(v+" "+((Object)v).getClass());
        });
    }

20 class java.lang.Long
22 class java.lang.Long
24 class java.lang.Long
26 class java.lang.Long
28 class java.lang.Long
30 class java.lang.Long

2.5mapToDouble

同2.4MapToLong

2.6asLongStream

IntStream的asLongStream方法,直接将int流转换为long类型的流,测试和运行结果如下:

   public static void testAsLongStream(){
        LongStream longStream = IntStream.rangeClosed(8, 12).asLongStream();
        longStream.forEach(v->{
            System.out.println(v+" "+((Object)v).getClass());
        });
    }

8 class java.lang.Long
9 class java.lang.Long
10 class java.lang.Long
11 class java.lang.Long
12 class java.lang.Long

2.7asDoubleStream

2.6asLongStream同理

2.8扁平化操作flatMap

flatMap将IntStream流中的元素依次处理,并将其每个元素转换为一个流,最终将每个流合成一个大的IntStream返回,测试和运行结果如下:

  public static void testFlatMap(){

        IntStream.of(1,2,3).flatMap(e -> IntStream.rangeClosed(0,e)).forEach(System.out::println);

    }

0
1
0
1
2
0
1
2
3

2.9去重操作distinct

利用distinct对流中重复的元素进行去重,测试和运行结果如下:

    public static void testDistinct(){
        IntStream.of(99,88,60,99,90,60).distinct().forEach(System.out::println);
    }

99
88
60
90

2.10排序操作sort

用于给元素排序,测试和运行结果如下:

private static void testSort() {
        IntStream.of(9, 80, 34, 2, 24).sorted().forEach(System.out::println);
    }

2

9

24

34

80

2.11查看元素peek

该操作可以获取每个元素然后给定特定的操作,测试和运行结果如下:

  public static void testPeek(){
       /*
        注意:peek后必须添加遍历操作,不然不会有任何输出
        
        由于peek方法需要传入的是一个IntConsumer接口实现类,所以我们得实现IntConsumer的accept方法,然而peek方法并不会去帮我们去调用我们重写accept方法,
        而是返回一个IntStream的另一个实现类StatelessOp的子类,通过重写StatelessOp的opWrapSink方法,该方法返回一个Sink.ChainedInt静态内部类,通过
        重写Sink.ChainedInt的accept方法,该方法去帮我们调用了IntConsumer的accept方法。最后通过foreach方法的内部操作帮我们调用了Sink.ChainedInt的accept方法 
        (通过简单分析源码而来,有不详细的地方请自行查看源码)
        */
        IntStream.range(1,10).peek(e-> System.out.printf("filter map element:%d\n",e)).mapToObj(e->String.valueOf(e)).forEach(System.out::println);
    }

filter map element:1
1
filter map element:2
2
filter map element:3
3
filter map element:4
4
filter map element:5
5
filter map element:6
6
filter map element:7
7
filter map element:8
8
filter map element:9
9

2.12跳过元素skip

使用skip跳过指定个数的元素,测试和输出结果如下:

private static void testSkip() {
        IntStream.rangeClosed(1, 9).skip(6).forEach(System.out::println);
    }

7
8
9

2.13顺序输出forEachOrdered

并行处理parallel,并行流输出的元素并不能保证按照原始顺序输出,如果需要,则可以使用forEachOrdered保证输出顺序(初始状态的顺序),测试和运行结果如下:

    public static void  testForEachOrdered(){
        System.out.println("forEach输出并行流中的元素");
        IntStream.of(5,10,20,4,19,50).parallel().forEach(value -> System.out.print(value+" "));
        System.out.println();
        System.out.println("forEachOrdered,按照初始顺序输出并行流:");
        IntStream.of(5,10,20,4,19,50).parallel().forEachOrdered(value -> System.out.print(value+" "));
    }

forEach输出并行流中的元素
4 19 50 5 20 10
forEachOrdered,按照初始顺序输出并行流:
5 10 20 4 19 50

2.14reduce规约

按照特点规则处理每个元素,然后返回处理后的结果,测试和运行结果如下:

public static void testReduce(){
        //求1到100的和
        System.out.println("1-100的和为:"+IntStream.rangeClosed(1,100).reduce((x,y)->x+y).getAsInt());
        //orElse和orElseGet可以防止返回值为空,如果为空则默认返回0
        System.out.println(IntStream.of().reduce((x, y) -> x + y).orElse(0));
        System.out.println(IntStream.of().reduce((x, y) -> x + y).orElseGet(() -> 0));
        System.out.println(IntStream.of().reduce((x, y) -> x + y).orElseThrow(()->new RuntimeException("参数为空,返回值为空")));
    }

1-100的和为:5050
0
0
Exception in thread "main" java.lang.RuntimeException: 参数为空,返回值为空
at Test.lambda$testReduce$19(Test.java:105)
at Test$$Lambda$6/1149319664.get(Unknown Source)
at java.util.OptionalInt.orElseThrow(OptionalInt.java:189)
at Test.testReduce(Test.java:105)
at Test.main(Test.java:8)

2.15装箱操作boxed

boxed用于将流中的元素转换为对应的对象类型,具体测试代码和输出如下:

 private static void testBoxed() {
        IntStream.of(2, 7).boxed().forEach(v -> System.out.println(v + " -> " + v.getClass()));
    }

2 -> class java.lang.Integer

7 -> class java.lang.Integer

2.16数学运算

最大值,最小值,平均值等数学操作,测试和输出如下

 private static void testMathOpt() {
        System.out.println("最大值:");
        System.out.println(IntStream.of(3, 90, 988, 1, 76).max().getAsInt());
        System.out.println("最小值:");
        System.out.println(IntStream.of(3, 90, 988, 1, 76).min().getAsInt());
        System.out.println("平均值:");
        System.out.println(IntStream.of(3, 90, 988, 1, 76).average().getAsDouble());
        System.out.println("元素个数:");
        System.out.println(IntStream.of(3, 90, 988, 1, 76).count());
        System.out.println("元素总和:");
        System.out.println(IntStream.of(3, 90, 988, 1, 76).sum());
        System.out.println("使用summaryStatistics进行数学运算:");
        IntSummaryStatistics summaryStatistics = IntStream.of(-2, 2, -9, 10, 9).summaryStatistics();
//        Assert.assertEquals(10, summaryStatistics.getSum());
        System.out.println("总和:" + summaryStatistics.getSum());
        System.out.println("最大值:" + summaryStatistics.getMax());
        System.out.println("最小值:" + summaryStatistics.getMin());
        System.out.println("元素个数:" + summaryStatistics.getCount());
        System.out.println("平均值:" + summaryStatistics.getAverage());
    }

最大值: 988

最小值: 1

平均值: 231.6

元素个数: 5

元素总和: 1158

使用summaryStatistics进行数学运算:

总和:10

最大值:10

最小值:-9

元素个数:5

平均值:2.0

2.17匹配操作

返回特定的元素,如首个元素等,测试和输出如下:

    private static void testMatchOpt() {
        boolean anyMatch = IntStream.of(-2, 2, -9, 10, 9).anyMatch(e -> e > 0);
//        Assert.assertTrue(result);
        System.out.println("anyMatch: " + anyMatch);
        boolean allMatch = IntStream.of(5, 5, 5, 5, 5).allMatch(e -> e > 0);
        System.out.println("allMatch: " + allMatch);
        boolean noneMatch = IntStream.of(4, 5, 5, 5).noneMatch(e -> e == 4);
        System.out.println("noneMatch: " + noneMatch);
    }

anyMatch: true

allMatch: true

noneMatch: false

2.18查询操作

返回特定的元素,如首个元素等,测试和输出如下:

private static void testFindOpt() {
        int findFirst = IntStream.of(4, 5, 5, 5).findFirst().getAsInt();
        System.out.println("findFirst: " + findFirst);
        int findAny = IntStream.of(42, 25, 52, 54).findAny().getAsInt();
        System.out.println("findAny: " + findAny);
    }

findFirst: 4

findAny: 42

posted @ 2023-06-23 09:36  哩个啷个波  阅读(1021)  评论(0编辑  收藏  举报