> 技术文档 > java的stream流_java stream流

java的stream流_java stream流

目录

0:在学习stream流之前回顾知识点

0.1:传统方式遍历集合

0.2:迭代器遍历集合

0.3:这两种方式的有优缺点

1:stream流的含义

2:stream流的优点

3:stream流使用

3.1:获取流

3.2:中间方法 用于过滤、排序、聚合

3.3:终结方法


0:在学习stream流之前回顾知识点

下图是容器的类图,可以看到最上层的接口是迭代器,我们这里为什么了解迭代器呢?

接着往下看,我们遍历数组一般使用两种方式,一种是传统方式,一种是迭代器方式。当我们了解到了这两种方式的优缺点之后,我们再来学习流

0.1:传统方式遍历集合

传统遍历元素:直接通过索引遍历集合(如数组),客户端需要知道集合的内部结构(如数组长度),不推荐在里边删除元素。

/** * 传统遍历元素 */ @Test public void T1(){ ArrayList list = new ArrayList(); list.add(\"a\"); list.add(\"b\"); list.add(\"c\"); list.add(\"c\"); list.add(\"d\"); //list的传统方式遍历 我们需要知道数组的长度 for (int i = 0; i < list.size(); i++) { System.out.println(\"传统遍历list:\"+list.get(i)); } } /** * 传统for遍历元素删除,这种方法不推荐 */ @Test public void T11(){ ArrayList list = new ArrayList(); list.add(\"a\"); list.add(\"b\"); list.add(\"c\"); list.add(\"c\"); list.add(\"d\"); //list的传统方式遍历 我们需要知道数组的长度 for (int i = 0; i < list.size(); i++) { //在for循环中删除元素c,会导致后边的元素前移,从而漏掉下一个元素,所以输出结果还有c if (list.get(i).equals(\"c\")){ list.remove(i); //list.remove(s); 错误方法 ConcurrentModificationException } } System.out.println(list); }

0.2:迭代器遍历集合

1:我们先看一下迭代器的方法,Java 的集合框架(如 List、Set)均实现了 Iterator 接口,通过iterator() 方法返回迭代器。迭代器被归类java设计模式里面的 行为型设计模式(Behavioral Design Pattern),定义了 对象之间的交互方式

它的核心思想是:解耦遍历逻辑,我们不关心他们具体的数据结构

适用于set、list、map。也就是说我们不关心他们的数据结构,只管用迭代器遍历就行,可以删除数据。

它通常包含以下核心方法:

hasNext():判断是否还有下一个元素。

next():获取下一个元素。

remove()(可选):删除当前元素。

2:迭代器遍历元素

删除元素的强制模数(修改次数)=预期模数,删除数据的时候回判断模数是否等于预期模数。保证了删除是数据安全。

0.3:这两种方式的有优缺点

传统方式遍历:需要根据索引下标遍历集合,需要知道集合的长度数据

迭代器方式遍历:解耦数据结构,通用迭代器遍历。不关心数据结构,提供了同一的访问接口,都是迭代器,缺点即使增加了额外的迭代器类

1:stream流的含义

stream流就像一种更高阶的迭代器,与传统的迭代器不一样,流不存储数据,只是代表了一个计算过程,在这个过程中对数据进行操作。比如过滤、排序、聚合操作。流就像一个管道,在这个管道中对数据操作、按照一定的规则流动。比传统迭代器多了过滤、排序、聚合等操作,功能更丰富。

2:stream流的优点

流的作用主要体现在以下几个方面:

函数式编程风格:流API提供了一套丰富的函数式编程特性,使得代码更简洁、可读性更强。我们可以用非常少的代码处理复杂的逻辑。

无状态操作:流的操作不会改变原始数据集合,它们是无状态的。这就像是音乐家们的乐器,演奏结束后,乐器仍然是原始的状态,没有被改变。

3:stream流使用

3.1:获取流

/** * 在使用Stream流过程中 * 1:获取流 * 2:处理流 * 2.1:中间方法 * 2.2:终结方法 */public class Steam获取流1 { //1:list获取流 list.stream() @Test public void t1() { List list = new ArrayList(); list.add(\"1\"); list.add(\"2\"); list.add(\"3\"); list.add(\"4\"); list.add(\"5\"); list.add(\"6\"); list.add(\"\"); list.add(null); Stream stream = list.stream(); stream.forEach(System.out::println);//终结方法 } //2:set获取流 set.stream() @Test public void t2() { Set set = new HashSet(); set.add(\"1\"); set.add(\"2\"); set.add(\"3\"); set.add(\"1\"); set.add(\"4\"); set.add(\"5\"); Stream stream = set.stream(); stream.forEach(System.out::println); } //3:map获取流 map.keySet().stream() @Test public void t3() { Map map = new HashMap(); map.put(\"11\", 1); map.put(\"22\", 2); map.put(\"33\", 3); map.put(\"44\", 4); System.out.println(\"=======\"); Stream stream = map.keySet().stream(); stream.forEach(System.out::println); System.out.println(\"=======\"); Stream<Map.Entry> stream1 = map.entrySet().stream(); stream1.forEach(entry -> System.out.println(entry.getKey() + \":\" + entry.getValue())); } //4:数组获取流 Arrays.stream() @Test public void t4() { int[] ints = new int[]{1, 2, 3, 4, 5}; Arrays.stream(ints).forEach(System.out::println); System.out.println(\"================\"); String[] strings = {\"1\", \"2\", \"3\", \"4\"}; Stream stream = Arrays.stream(strings); stream.forEach(System.out::println); } //5:stream流直接创建 Stream.of() @Test public void t5() { Stream stream = Stream.of(1, 2, 3, 4, 5); stream.forEach(System.out::println); System.out.println(\"==============\"); Stream stream1 = Stream.of(\"a\",\"b\",\"c\",\"d\"); stream1.forEach(System.out::println); Integer[] ints = {1, 2, 3, 4, 5}; String[] strings = {\"1\", \"2\", \"3\", \"4\"}; Stream.of(ints).forEach(System.out::println); System.out.println(\"=============\"); Stream.of(strings).forEach(System.out::println); }}

3.2:中间方法 用于过滤、排序、聚合

/** * stream流体验 过滤 * 代码简单,不改变原始流 */ @Test public void t1(){ List peoples = List.of( new Person(\"北京\", 15, \"Jack1\"), new Person(\"洛阳\", 18, \"Jack2\"), new Person(\"深圳\", 30, \"Jack3\"), new Person(\"杭州\", 45, \"Jack4\"), new Person(\"青岛\", 50, \"Jack5\") ); //传统for循环,需要过滤age大于18的,代码比较多 List people18=new ArrayList(); for (Person people : peoples) { System.out.println(\"增强for:\"+people); if (people.getAge()>18){ people18.add(people); } } //Stream流初体验,filter过滤年龄大于18的person,函数式编程 //代码简单,返回新的集合,原来的集合不变,这就是无状态,不改变原始数据 List newlist = peoples.stream() .filter(person -> person.getAge() > 18) .toList(); newlist.forEach(System.out::println);//新的集合 System.out.println(\"=====\"); peoples.forEach(System.out::println);//原始集合不变 } //1.1:filter 中间方法 过滤 @Test public void filter1() { List people = List.of( new Person(\"北京\", 15, \"Jack1\"), new Person(\"洛阳\", 18, \"Jack2\"), new Person(\"深圳\", 30, \"Jack3\"), new Person(\"杭州\", 45, \"Jack4\"), new Person(\"青岛\", 50, \"Jack5\"), new Person(\"青岛\", 50, \"Jack5\") ); List list = people.stream().filter(new Predicate() { @Override public boolean test(Person person) { //返回值为true,数据留下,否则抛弃 return person.getAge() > 30; } }).toList(); list.forEach(System.out::println); System.out.println(\"========简化写法========\"); people.stream() .filter(p -> p.getAge() > 30) .filter(person -> person.getName().contains(\"Jack5\")) .forEach(System.out::println); } //1.2:filter 中间方法 过滤 @Test public void filter2() { List list = new ArrayList(); list.add(\"张无忌\"); list.add(\"张三丰\"); list.add(\"张三丰\"); list.add(\"张强\"); list.add(\"周芷若\"); list.add(\"赵敏\"); Stream stringStream = list.stream() .filter(name -> name.startsWith(\"张\")); stringStream.forEach(System.out::println); //报错,一旦使用了终结方法,stream就会被关闭 //stringStream.filter(name->name.startsWith(\"张三\")).forEach(System.out::println); } //2:limit 中间方法 指定范围 @Test public void limit() { List list = new ArrayList(); list.add(\"张无忌\"); list.add(\"张三丰\"); list.add(\"张三丰\"); list.add(\"张强\"); list.add(\"周芷若\"); list.add(\"赵敏\"); list.stream().limit(3).forEach(System.out::println); //forEach 是终结方法 } //3:skip 中间方法 跳过2个元素 @Test public void spip() { List list = new ArrayList(); list.add(\"张无忌\"); list.add(\"张三丰1\"); list.add(\"张三丰2\"); list.add(\"张强\"); list.add(\"周芷若\"); list.add(\"赵敏\"); list.stream().skip(2).forEach(System.out::println); System.out.println(\"===============\"); list.stream().limit(3).skip(2).forEach(System.out::println); } //4:distinct 中间方法 去重复元素 @Test public void distinct() { List list = new ArrayList(); list.add(\"张无忌\"); list.add(\"张三丰\"); list.add(\"张三丰\"); list.add(\"张强\"); list.add(\"周芷若\"); list.add(\"赵敏\"); list.stream().distinct().forEach(System.out::println); } //5:concat 中间方法 合并两个流的数据 @Test public void concat() { Stream stringStream1 = Stream.of(\"1\", \"2\", \"3\", \"a\"); Stream stringStream2 = Stream.of(\"a\", \"b\", \"c\"); Stream concat = Stream.concat(stringStream1, stringStream2); concat.distinct().forEach(System.out::println); //.distinct().forEach(System.out::println); } //6:map 中间方法 转换流的数据类型 @Test public void map() { List list = new ArrayList(); Collections.addAll(list, \"张三1-21\", \"张三2-22\", \"张三3-23\", \"张三4-24\", \"张三5-25\"); System.out.println(\"========分割线=======\"); list.stream().map(new Function() { @Override public String apply(String s) { System.out.println(\"传递得到:\"+s); String[] split = s.split(\"-\"); String name=split[0]; String age=split[1]; return age; } }).forEach(System.out::println); System.out.println(\"========分割线,简化写法=======\"); list.stream() .map(s -> Integer.parseInt(s.split(\"-\")[1])) .forEach(System.out::println); }

3.3:终结方法

/** * 在使用Stream流过程中 * 1:获取流 * 2:处理流 * 2.1:中间方法 * 2.2:终结方法 */public class Steam终结方法3 { //1:forEach 终结方法, @Test public void forEach() { List people = List.of( new Person(\"北京\", 15, \"Jack1\"), new Person(\"洛阳\", 18, \"Jack2\"), new Person(\"深圳\", 30, \"Jack3\"), new Person(\"杭州\", 45, \"Jack4\"), new Person(\"青岛\", 50, \"Jack5\"), new Person(\"青岛\", 50, \"Jack5\") ); people.stream().forEach(new Consumer() {  @Override  public void accept(Person person) {  System.out.println(person);  } }); System.out.println(\"======终结方法======\"); people.stream().forEach(person -> System.out.println(person)); System.out.println(\"======终结方法======\"); people.stream().forEach(System.out::println); } //2:count 终结方法, @Test public void count() { List people = List.of( new Person(\"北京\", 15, \"Jack1\"), new Person(\"洛阳\", 18, \"Jack2\"), new Person(\"深圳\", 30, \"Jack3\"), new Person(\"杭州\", 45, \"Jack4\"), new Person(\"青岛\", 50, \"Jack5\"), new Person(\"青岛\", 50, \"Jack5\") ); long count = people.stream().count(); System.out.println(\"长度:\"+count); } //2:toArray 终结方法 准换成数组 @Test public void toArray() { List people = List.of( new Person(\"北京\", 15, \"Jack1\"), new Person(\"洛阳\", 18, \"Jack2\") ); Object[] array = people.stream().toArray(); System.out.println(\"长度:\"+array.length); for (Object o : array) { System.out.println(o); } } //3:toList toSet toMap //map的 // 终结方法 转换成list @Test public void toList(){ List list = new ArrayList(); Collections.addAll(list, \"张三1-男-21\", \"张三1-男-21\",\"张三2-男-22\", \"丽丽3-女-23\", \"张三4-男-24\", \"丽丽5-女-25\"); System.out.println(\"======toList=====\"); List list1 = list.stream() .filter(s -> \"男\".equals(s.split(\"-\")[1])) .toList(); list1.forEach(System.out::println); System.out.println(\"======toSet=====\"); Set set = list.stream() .filter(s -> \"男\".equals(s.split(\"-\")[1])) .collect(Collectors.toSet()); set.forEach(System.out::println); System.out.println(\"======toMap=====\"); Map map = list.stream() .filter(s -> \"男\".equals(s.split(\"-\")[1])) .distinct() //必须去重,key不能重复 .collect(Collectors.toMap(n -> n.split(\"-\")[0], n -> n.split(\"-\")[1])); map.forEach((k, v) -> System.out.println(k + \"=\" + v)); }}