下面直观点了解Stream:
- Stream是Java8 新增的流特性,目的是让程序员写出高效率、干净、简洁的代码
- Stream类似于SQL语句,可以对代码进行集合运算和表达
- Stream就是把元素看成一种流,流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
Stream使用格式成如下图 :
构建Stream ------------中间操作----------------------终端操作
注意:在没有终端操作 的前提下,中间操作即生成流不会执行
数据源:分为串行流Stream和并行流parallelStream()
列举一下构建串行流的方式,与并行流类似
/** * Created with IntelliJ IDEA. * * @Author: DIXian * @Date: 2021/07/04/19:31 */ public class Test04 { public static void main(String[] args) { List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6); Stream<Integer> stream = integers.stream(); stream.forEach(System.out::println); } }
2. 通过集合Collection.stream
@Test public void test01(){ ArrayList<Object> list = new ArrayList<>(); list.add(2); list.add(3); list.add(4); list.add(5); list.add(6); list.stream().forEach(System.out:: println); } }
3. 通过Stream的静态of()方法Stream.of
@Test public void test02(){ Stream.of(2, 3, 4, 5).forEach(System.out :: println); } }
4. 通过创建无限流的两种方式
@Test public void test03(){ //seed :给定一个初始值 ,后一个参数 T -> t ,此处加个一个截断操作 limit(10) Stream.iterate(0, item -> item+2).limit(10).forEach(System.out :: println); }
生成流:即对构建好的进行中间操作
1. filter():filter(): 返回结果生成新的流中只包含满足筛选条件的数据。
public void test04(){ List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6); integers.stream().filter(item -> item.equals(1)).forEach(System.out :: println); }
2.map():将流中的元素进行再次加工形成一个新流,流中的每一个元素映射为另外的元素。
// 2、map:返回元素的大写类型和哈希值 List<String> mzc = Arrays.asList("ma", "zhi", "chu"); List<String> mzcUpperCase = mzc.stream(). map(n -> n.toUpperCase()). collect(Collectors.toList()); List<Integer> mzcHashCode = mzc.stream().map(n -> n.hashCode()).collect(Collectors.toList()); System.out.println("mzcUpperCase:"+mzcUpperCase+" ----- mzcHashCode:"+mzcHashCode);
运行结果:
mzcUpperCase:[MA, ZHI, CHU] ----- mzcHashCode:[3476, 120571, 98480]
示例场景:取出商品的所有id,就可以这样写(伪代码):
List<Product> productList = productService.selectAll();
List<Integer> pIds = productList.stream().map(p->p.getId).collect(Collectors.toList());
这样就可以拿到所有商品id的集合。
3.flatMap():扁平化映射,它具体的操作是将多个stream连接成一个stream,这个操作是针对类似多维数组的,比如集合里面包含集合,相当于降维作用,类似list中的addAll()操作
flatMap是将流中的每个元素都放到一个流中,最后将所有的流合并成一个新流,所有流对象中的元素都合并到这个新生成的流中返回。
// flatMap:将多层集合中的元素取出来,放到一个新的集合中去 List<Integer> num1 = Arrays.asList(1, 2, 3); List<Integer> num2 = Arrays.asList(4, 5, 6); List<Integer> num3 = Arrays.asList(7, 8, 9); List<List<Integer>> lists = Arrays.asList(num1, num2, num3); Stream<Integer> outputStream = lists.stream().flatMap(l -> l.stream()); List<Integer> flatMapResult = outputStream.sorted().collect(Collectors.toList()); System.out.println(flatMapResult);
运行结果:[1, 2, 3, 4, 5, 6, 7, 8, 9]
示例场景:取出所有部门人员的姓名,就可以这样写(伪代码):
// 1、取出所有部门
List<Department> departments = ...;
// 2、这个时候可以利用flatMap先将所有部门的所有人员汇聚起来
List<Person> persons = departments.stream.flatMap(d->d.getPersonList()).collect(Collectors.toList());
// 3、再利用map()方法取出
4.distinct():顾名思义,将流中的元素去重之后输出。
List<String> mzc = Stream.of("ma","zhi","chu","zhi","shuo","ma") .distinct() .collect(Collectors.toList()); System.out.println(mzc);
运行结果:
[ma, zhi, chu, shuo]
5.sorted():这个很简单了,顾名思义,将流中的元素按照自然排序方式进行排序。
// sorted:自然顺序排序 List<Integer> nums = Arrays.asList(1, 3, 5, 6, 8, 2); List<Integer> sortedNum = nums.stream().sorted().collect(Collectors.toList()); System.out.println(sortedNum); // sorted:降序排序 List<Integer> sortedNum2 = nums.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList()); System.out.println(sortedNum2); // sorted:使用Comparator List<Integer> sortedNums3 = nums.stream().sorted(Comparator.comparing(n -> n)).collect(Collectors.toList()); System.out.println(sortedNums3); // 不用stream直接顺序排序 nums.sort(Comparator.comparing(Integer::intValue)); System.out.println(nums); //不用stream直接降序排序 nums.sort(Comparator.comparing(Integer::intValue).reversed()); System.out.println(nums);
运行结果:
[1, 2, 3, 5, 6, 8]
[8, 6, 5, 3, 2, 1]
[1, 2, 3, 5, 6, 8]
[1, 2, 3, 5, 6, 8]
[8, 6, 5, 3, 2, 1]
6.peek():对流中每个元素执行操作,并返回一个新的流,返回的流还是包含原来流中的元素。
// peek(): String[] arr = new String[]{"a","b","c","d"}; Arrays.stream(arr) .peek(System.out::println) //a,b,c,d .count(); // peek()+filter() Stream.of("ma", "zhi", "chu") .filter(e -> e.length() > 2) .peek(e -> System.out.println(e)) .collect(Collectors.toList());
运行结果:
a
b
c
d
zhi
chu
7、limit():顾名思义,返回指定数量的元素的流。返回的是Stream里前面的n个元素。
// limit():取出100中的前十个 List<Integer> limitNum = IntStream.range(1,100).limit(10) .boxed() .collect(Collectors.toList()); System.out.println(limitNum); // limit():取出前4个单词 List<String> words = Arrays.asList("ma", "zhi", "chu", "wait", "you", "follow"); List<String> limitWord = words.stream().limit(4).collect(Collectors.toList()); System.out.println(limitWord);
运行结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[ma, zhi, chu, wait]
8.skip():和limit()相反,将前几个元素跳过(取出)再返回一个流,如果流中的元素小于或者等于n,就会返回一个空的流。
// skip():跳过前面三个单词再返回 List<String> words = Arrays.asList("ma", "zhi", "chu", "wait", "you", "follow"); List<String> skipWord = words.stream().limit(4).collect(Collectors.toList()); System.out.println(skipWord); // skip():跳过全部单词再返回 List<String> emptyWord = words.stream().skip(6).collect(Collectors.toList()); System.out.println(emptyWord); // skip():跳过超过单词长度的数目再返回 List<String> emptyWord2 = words.stream().skip(10).collect(Collectors.toList()); System.out.println(emptyWord);
运行结果:
[91, 92, 93, 94, 95, 96, 97, 98, 99]
[ma, zhi, chu, wait]
[]
[]
聚合操作:即对流进行终端操作
1.forEach():遍历流中的每一个元素,按照指定的方法执行,执行顺序不一定按照流的顺序。
// foreach:遍历流中每一个元素,执行顺序按照流的顺序 Stream.of(1,2,3,4,5,6).forEach(System.out::println); // foreach:遍历流中每一个元素,执行顺序不一定按照流的顺序,.parallel()表示创建一个并行流 Stream.of(1,2,3,4,5,6).parallel().forEach(System.out::println);
2.forEachOrdered():遍历流中的每一个元素,按照指定的方法执行,执行顺序按照流的顺序。
// forEachOrdered():遍历流中每一个元素,执行顺序按照流的顺序 Stream.of(1,2,3,4,5,6).forEachOrdered(System.out::println); // forEachOrdered:遍历流中每一个元素,执行顺序按照流的顺序,.parallel()表示创建一个并行流 Stream.of(1,2,3,4,5,6).parallel().forEachOrdered(System.out::println);
运行结果:
1
2
3
4
5
6
1
2
3
4
5
6
3.toArray():将流中的元素放入到一个数组中
// toArray():将流中的元素放入到一个数组中 String[] strings = Stream.of("ma", "zhi", "chu").toArray(String[]::new); System.out.println(Arrays.toString(strings));
运行结果:[ma, zhi, chu]
4.reduce():这个方法的主要作用是把 Stream 元素组合起来。它提供一个起始值(种子),然后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合。从这个意义上说,字符串拼接、数值的 sum、min、max、average 都是特殊的 reduce。
// reduce():字符串拼接 String reduceStr1 = Stream.of("ma", "zhi", "chu").reduce("", String::concat); String reduceStr2 = Stream.of("ma", "zhi", "chu").reduce("", (x,y)->x+y); System.out.println(reduceStr1); System.out.println(reduceStr2); // reduce():求和,identity(起始值)为0 Integer total1 = Stream.of(1,2,3,4).reduce(0, Integer::sum); Integer total2 = Stream.of(1,2,3,4).reduce(0, (x, y) -> x +y); System.out.println(total1); System.out.println(total2); // 求和,sumValue = 10, 无起始值 Integer total3 = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get(); System.out.println(total3); // reduce():求最小值 double minValue = Stream.of(-1.1, 8.8, -2.2, -6.6).reduce(Double.MAX_VALUE, Double::min); System.out.println(minValue);
运行结果:
mazhichu
mazhichu
10
10
10
-6.6
5.collect():是Stream的一个函数,负责收集流。前面我们说中间操作是将一个流转换成另一个流,这些操作是不消耗流的,但是终端操作会消耗流,产生一个最终结果,collect()就是一个规约操作,将流中的结果汇总。结果是由传入collect()中的Collector定义的
// collect():负责收集流,将结果汇总,比如将下面的流中的结果汇总到一个集合中去 List<Integer> skipNum = IntStream.range(1,100).skip(90) .boxed() .collect(Collectors.toList()); System.out.println(skipNum);
运行结果:[91, 92, 93, 94, 95, 96, 97, 98, 99]
6.min():返回流中的最小值
// min():返回流中的最小值 List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6); Integer minNum = nums.stream().min(Integer::compareTo).get(); Integer min = nums.stream().min((x,y) -> x.compareTo(y)).get(); System.out.println(minNum); System.out.println(min);
运行结果:
1
1
7.max():返回流中的最大值
// max():返回流中的最大值 List<Integer> num = Arrays.asList(1, 2, 3, 4, 5, 6); Integer maxNum = num.stream().max(Integer::compareTo).get(); Integer max = num.stream().max(Comparator.comparing(Function.identity())).get(); System.out.println(maxNum); System.out.println(max);
运行结果:
6
6
8.count():返回流中元素的数量
// count():返回流中元素的数量 List<Integer> ls = Arrays.asList(1,2,3,4,5); long count = ls.stream().count(); long count1 = ls.stream().filter(l -> l > 2).count(); System.out.println(count); System.out.println(count1);
运行结果:
5
3
9.anyMatch():Stream 中只要有一个元素符合传入的断言,就返回 true,否则返回false。
// anyMatch():判断流中数据是否有一个复合断言 List<Integer> ins = Arrays.asList(1,2,3,4,5); boolean b = ins.stream().anyMatch(l -> l > 2); boolean b1 = ins.stream().anyMatch(l -> l > 5); System.out.println(b); System.out.println(b1); // anyMatch():判断流中数据是否有一个复合断言,如果流为空,永远返回false List<Integer> inss = Arrays.asList(); boolean b2 = inss.stream().anyMatch(l -> l > 2); System.out.println(b2);
运行结果:
true
false
false
10.allMatch():Stream 中所有元素都符合传入的断言时返回 true,否则返回false,流为空时总是返回true。
// allMatch():判断流中元素是否都符合断言条件 List<Integer> ints = Arrays.asList(1,2,3,4,5); boolean c = ints.stream().allMatch(l -> l > 0); boolean c1 = ints.stream().allMatch(l -> l > 1); System.out.println(c); System.out.println(c1); // allMatch():判断流中元素是否都符合断言条件,如果流为空,永远返回true List<Integer> emptyList = new ArrayList<>(); boolean c2 = emptyList.stream().allMatch(e -> e > 1); System.out.println(c2);
运行结果:
true
false
true
11.noneMatch():Stream 中所有元素都不满足传入的断言时返回 true,否则返回false。
// noneMatch():判断流中元素是否都不符合传入的断言条件 List<Integer> numList = Arrays.asList(1,2,3,4,5); boolean d = numList.stream().noneMatch(l -> l > 6); boolean d1 = numList.stream().noneMatch(l -> l > 1); System.out.println(d); System.out.println(d1); // noneMatch():判断流中元素是否都不符合传入的断言条件,流为空时永远返回true List<Integer> numist = Arrays.asList(); boolean d2 = numist.stream().noneMatch(l -> l > 6); System.out.println(d2);
运行结果:
true
false
true
12.findFirst():总是返回流中的第一个元素,如果流为空,返回一个空的Optional.
// findFirst():返回流中的第一个元素 List<Integer> integers = Arrays.asList(1, 2, 3); Optional<Integer> first = integers.stream().findFirst(); System.out.println(first); System.out.println(first.isPresent()); // 判断是否不等于null,isPresent()相当于!=null的判断 System.out.println(first.get()); //findFirst():返回流中的第一个元素,如果流为空,返回一个空的Optional List<Integer> lls = Collections.EMPTY_LIST; Optional<Integer> first1 = lls.stream().findFirst(); System.out.println(first1); System.out.println(first1.isPresent());
运行结果:
Optional[1]
true
1
Optional.empty
false
13.findAny():返回流中的任意一个元素即可,如果流为空,返回一个空的Optional.
// findAny():返回流中任意一个元素, List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6); Optional<Integer> any = list.stream().findAny(); // 并行流下每次返回的结果会不同 // Optional<Integer> any = list.stream().parallel().findAny(); System.out.println(any); System.out.println(any.isPresent()); System.out.println(any.get()); // findAny():返回流中任意一个元素,如果流为空,返回一个空的Optional List<Integer> list1 = Arrays.asList(); Optional<Integer> any1 = list1.stream().findAny(); System.out.println(any1); System.out.println(any1.isPresent());
运行结果:
Optional[1]
true
1
Optional.empty
false
以上即为Stram的流程操作理解
可参考:https://www.cnblogs.com/mazhichu/p/11983451.html