源码 。
IntStream是一种特殊的stream,用来提供对int相关的stream操作,下面我们一起来看下。
用来生成无限个数整数对应的stream,对于需要持续获取随机值的场景可以考虑使用这种方式。
class FakeCls {
void fakeMethod() {
Random random = new Random();
IntStream.generate(() -> random.nextInt(1000)).forEach(value -> {
System.out.println(value);
});
}
}
通过IntSupplier() -> random.nextInt(1000)
获取持续不断的数字序列,然后通过forEach获取,输出如下:
603
154
921
526
364
773
82
408
412
...省略其他...
生成某个数字范围内的数字集合的stream,range是左闭右开的,对应的还有一个rangeClose,是左闭右闭的。
class FakeCls {
void fakeMethod() {
System.out.println("range: 左闭右开");
IntStream.range(1, 5).forEach(value -> System.out.println(value));
System.out.println("rangeClose: 左闭右闭");
IntStream.rangeClosed(1, 5).forEach(value -> System.out.println(value));
}
}
输出如下:
range: 左闭右开
1
2
3
4
rangeClose: 左闭右闭
1
2
3
4
5
使用给定的一组值创建stream。
class FakeCls {
private static void testOf() {
IntStream.of(9, 90, 876, 12).forEach(v -> System.out.println(v));
}
}
输出如下:
9
90
876
12
Process finished with exit code 0
创建一个不包含任何元素的空流。
class FakeCls {
private static void testEmpty() {
int sum = IntStream.empty().sum();
System.out.println(sum);
System.out.println("---完美的分割线---");
IntStream.empty().forEach(v -> System.out.println(v));
}
}
输出如下:
类似于构造器设计模式的stream创建方式,可以通过构造器添加若干个元素,然后通过build方法获取流对象。
class FakeCls {
private static void testBuilder() {
IntStream.builder().add(90).add(87).build().forEach(v -> System.out.println(v));
}
}
输出如下:
90
87
Process finished with exit code 0
迭代处理某个初始整数值的stream,比如对某个初始整数值一直做*2
。
class FakeCls {
private static void testIterator() {
// 第一个参数seed:初始值
// 第二个参数IntUnaryOperator:用于根据当前元素生成下一个元素的类
// 依次*2,生成下一个元素
IntStream iterate = IntStream.iterate(1, operand -> operand * 2);
// 限制10条,默认无限输出
IntStream limit = iterate.limit(10);
limit.forEach(v -> System.out.println(v));
}
}
输出如下:
1
2
4
8
16
32
64
128
256
512
Process finished with exit code 0
该操作用于合并两个stream。
class FakeCls {
private static void testConcat() {
IntStream range = IntStream.range(1, 5);
IntStream range1 = IntStream.rangeClosed(90, 95);
IntStream concat = IntStream.concat(range, range1);
concat.forEach(v -> System.out.println(v));
}
}
输出如下:
1
2
3
4
90
91
92
93
94
95
Process finished with exit code 0
通过filter来过滤不满足要求的数据,如下代码和输出结果:
class FakeCls {
private static void testFilter() {
// 过滤偶数
IntStream.rangeClosed(1, 10).filter(value -> value % 2 == 0).forEach(v -> System.out.println(v));
}
}
2
4
6
8
10
Process finished with exit code 0
map操作用于操作当前所有的元素,根据给定的操作生成新值,并用新值替代旧值,比如每个值都扩大2倍,如下代码和输出:
class FakeCls {
private static void testMap() {
IntStream originStream = IntStream.rangeClosed(1, 10);
IntStream intStream = originStream.map(v -> v * 2);
intStream.forEach(v -> System.out.println(v));
}
}
2
4
6
8
10
12
14
16
18
20
Process finished with exit code 0
通过mapObj可以将元素转成其他类型,具体转换类型通过实现类确定,测试代码和输出如下:
class FakeCls {
private static void testMapObj() {
Stream<String> stringStream = IntStream.rangeClosed(1, 5).mapToObj(value -> String.valueOf(value));
stringStream.forEach(v -> System.out.println(v + "->" + v.getClass()));
}
}
1->class java.lang.String
2->class java.lang.String
3->class java.lang.String
4->class java.lang.String
5->class java.lang.String
Process finished with exit code 0
将元素转换为Long类型,可以认为是2.3:转换元素mapObj
的确定类型版本,使用起来更加方便和明确,测试代码和输出如下:
class FakeCls {
private static void testMapLong() {
// 转换为*2的long值
LongStream longStream = IntStream.rangeClosed(1, 5).mapToLong(v -> v * 2);
longStream.forEach(v1 -> System.out.println(v1 + " -> " + ((Object)v1).getClass()));
}
}
2 -> class java.lang.Long
4 -> class java.lang.Long
6 -> class java.lang.Long
8 -> class java.lang.Long
10 -> class java.lang.Long
Process finished with exit code 0
同2.4:转换元素mapLong
。
直接转换为Long类型的stream,是一个为了简化操作提供的API,测试代码和输出如下:
class FakeCls {
private static void testAsLongStream() {
long[] longs = IntStream.rangeClosed(1, 10).asLongStream().toArray();
for (long aLong : longs) {
System.out.println(aLong);
}
}
}
1
2
3
4
5
6
7
8
9
10
Process finished with exit code 0
同2.6:转换元素asLongStream
。
该操作用于对IntStream中的每个元素依次进行处理,并使用该值(也可以不使用)来生成一个新的IntStream,最终将若干个IntStream合并成一个大的IntStream返回,如下测试代码和输出:
class FakeCls {
private static void testFlatMap() {
// 这里根据上游的元素扩展出了更多的元素
// 操作步骤如下:
// 1:获取值1,执行IntStream.rangeClosed(0, 1),生成0,1的IntStream
// 2:获取值2,执行IntStream.rangeClosed(0, 2),生成0,1,2的IntStream
// 3:获取值3,执行IntStream.rangeClosed(0 3),生成0,1,2,3的IntStream
// 4:合并以上的3个IntStream,生成0,1,0,1,2,0,1,2,3的IntStream为最终结果
IntStream.of(1, 2, 3).flatMap(e -> IntStream.rangeClosed(0, e)).forEach(System.out::println);
}
}
0
1
0
1
2
0
1
2
3
Process finished with exit code 0
用于去除重复元素,测试代码和输出如下:
class FakeCls {
private static void testDistinct() {
IntStream.of(1, 2, 3, 3, 4, 2).distinct().forEach(System.out::println);
}
}
1
2
3
4
Process finished with exit code 0
用于给元素排序,测试代码和输出如下:
class FakeCls {
private static void testSort() {
IntStream.of(9, 80, 34, 2, 24).sorted().forEach(System.out::println);
}
}
2
9
24
34
80
Process finished with exit code 0
该操作可以在获取每个元素后执行给定的操作,测试代码和输出如下:
class FakeCls {
private static void testPeek() {
IntStream.of(1, 2, 3, 4, 5)
// .filter(e -> e >= 3)
.peek(value -> System.out.printf("filter element: %d\n", value))
.mapToObj(String::valueOf)
.forEach(System.out::println);
}
}
filter element: 1
1
filter element: 2
2
filter element: 3
3
filter element: 4
4
filter element: 5
5
Process finished with exit code 0
不清楚为什么peek后必须有操作才能输出peek中的内容,清楚的朋友还望
不吝赐教
。
使用skip跳过指定个数的元素,测试代码和输出如下:
class FakeCls {
private static void testSkip() {
IntStream.rangeClosed(1, 9).skip(6).forEach(System.out::println);
}
}
7
8
9
Process finished with exit code 0
并行处理parallel保证按照原始顺序注意不是排序
输出,测试代码和输出如下:
class FakeCls {
private static void testSortOrdered() {
System.out.println("parallel 后顺序打乱");
IntStream.of(1,5,-9,0,-5,2,5,8).parallel().forEach(System.out::println);
System.out.println("parallel 后顺序保持不变");
// 在并行遍历时,forEachOrdered将顺序遍历元素
IntStream.of(1,5,-9,0,-5,2,5,8).parallel().forEachOrdered(System.out::println);
}
}
parallel 后顺序打乱
2
-5
8
5
-9
0
1
5
parallel 后顺序保持不变
1
5
-9
0
-5
2
5
8
Process finished with exit code 0
按照给定规则依次处理每个元素,最终获取一个结果,测试代码和输出如下:
class FakeCls {
private static void testReduce() {
// 规约操作一定有值
int sum = IntStream.range(0, 10).reduce(0, (v1, v2) -> v1 + v2);
System.out.println("sum is: " + sum);
// 相当于如下代码
int result = 0;
for (int i = 0; i < 10; i++) {
result = result + i;
}
System.out.println("result is: " + result);
}
}
sum is: 45
result is: 45
Process finished with exit code 0
再比如获取最小值测试代码和输出:
class FakeCls {
private static void testReduce1() {
// int[] arr = new int[] { 8, 90, 87, 43, 900, 12 };
// int minVal = Integer.MAX_VALUE;
// 获取最小值,执行过程如下:
// Integer.min(left, right) -> Integer.min(8, 90) = 8
// Integer.min(left, right) -> Integer.min(8, 7) = 7
// Integer.min(left, right) -> Integer.min(7, 43) = 7
// Integer.min(left, right) -> Integer.min(7, 5) = 5
// Integer.min(left, right) -> Integer.min(5, 12) = 5 最终结果
int minVal = IntStream.of(8, 90, 7, 43, 5, 12).reduce((left, right) -> {
System.out.printf("left: %d, right: %d", left, right);
System.out.println();
return Integer.min(left, right);
}).getAsInt();
System.out.println("minVal: " + minVal);
}
}
left: 8, right: 90
left: 8, right: 7
left: 7, right: 43
left: 7, right: 5
left: 5, right: 12
minVal: 5
Process finished with exit code 0
boxed用于将流中的元素转换为对应的对象类型,具体测试代码和输出如下:
class FakeCls {
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
Process finished with exit code 0
最大值,最小值,平均值等数学操作,测试代码和输出如下:
class FakeCls {
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
Process finished with exit code 0
判断元素是否满足给定要求,测试代码和输出如下:
class FakeCls {
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
Process finished with exit code 0
返回特定的元素,如首个元素等,测试代码和输出如下图所示:
class FakeCls {
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
Process finished with exit code 0