结合了Lambda表达式,简化集合,数组操作
使用步骤:
获取方式 | 方法名 | 说明 |
---|---|---|
单列集合 | default Stream |
Collection 中的默认方法 |
双列集合 | 无 | 无法直接使用 stream 流 |
数组 | public static |
Arrays 工具类中的静态方法 |
一堆零散数据 | public static |
Stream 接口中的静态方法 |
双列集合无法直接使用Stream流,可以使用keySet(),和entrySet()方法
下面举四个例子来分别解释单列集合,双列集合,数组,一堆零散数据
在Java的Stream API中,forEach
方法用于对Stream中的每个元素执行指定的操作。它是一个终端操作,意味着调用forEach
后会关闭流,无法再进行其他操作。
forEach
方法接收一个Consumer
函数式接口作为参数,该接口接受一个输入参数并返回void
。通常用于遍历流中的元素并执行某些操作,例如打印或修改元素。
List list = Arrays.asList("a", "b", "c");
list.stream().forEach(System.out::println);
虽然forEach
方法与传统的for-each循环都可以用于遍历集合,但它们有一些不同之处。forEach
是Stream API的一部分,适用于流式处理,而for-each循环是Java语言的基础语法。
在并行流中,forEach
方法的执行顺序是不确定的,因为元素可能被多个线程并发处理。如果需要保持顺序,可以使用forEachOrdered
方法。
List list = Arrays.asList("a", "b", "c");
list.parallelStream().forEachOrdered(System.out::println);
forEach
方法通常用于执行副作用操作(如打印或修改外部状态),而不是用于生成新的流或集合。如果需要生成新的流或集合,应使用map
、filter
等方法。
forEach
方法是Stream API中用于遍历元素的便捷工具,适用于需要对每个元素执行操作的场景。但在并行流中使用时需注意顺序问题,并且应避免将forEach
用于生成新流或集合的操作。
单列集合:default Stream
package com.itheima.demo1;
import java.util.ArrayList;
import java.util.Collections;
public class StreamDemo1 {
public static void main(String[] args) {
// 获取方式 方法名 说明
// 单列集合 default Stream stream() Collection 中的默认方法
// 双列集合 无 无法直接使用 stream 流
// 数组 public static Stream stream(T[] array) Arrays 工具类中的静态方法
// 一堆零散数据 public static Stream of(T... values) Stream 接口中的静态方法
ArrayList list = new ArrayList<>();
Collections.addAll(list,"e","b","c","d");
//// 获取一条流水线并把集合中的数据放在流水线中
// Stream stream = list.stream();
//// 使用终结方法打印流水线上的所有数据
// stream.forEach(new Consumer() {
// @Override
// public void accept(String s) {
//// s:依次表示流水线上的每一个数据
// System.out.println(s);
// }
// });
list.stream().forEach(s->System.out.println(s));
}
}
双列集合 无 无法直接使用 stream 流
package com.itheima.demo1;
import java.util.HashMap;
public class StreamDemo3 {
public static void main(String[] args) {
// 双列集合 无 无法直接使用 stream 流
// 双列集合不能直接使用Stream流,需要转换
// 创建双列集合
HashMap hm=new HashMap<>();
// 添加数据
hm.put("a",1);
hm.put("b",2);
hm.put("c",3);
hm.put("d",4);
// 第一种获取Stream流
// hm.keySet().stream().forEach(s->System.out.println(s));
// 第二种获取Stream流的方法
// hm.values().stream().forEach(s->System.out.println(s));
}
}
数组 public static
package com.itheima.demo1;
import java.util.Arrays;
public class StreamDemo4 {
public static void main(String[] args) {
// 数组 public static Stream stream(T[] array) Arrays 工具类中的静态方法
// 1.创建数组
int[] a = {1,2,3,4,5,6,7,8,9,10};
String[] b={"a","b"};
// 2.获取Stream流方法
Arrays.stream(a).forEach(s->System.out.print(s));
System.out.println();
System.out.println("========================");
Arrays.stream(b).forEach(s->System.out.print(s));
}
}
一堆零散数据 public static
package com.itheima.demo1;
import java.util.stream.Stream;
public class StreamDemo5 {
public static void main(String[] args) {
// 一堆零散数据 public static Stream of(T... values) Stream 接口中的静态方法
// 零散数据必须是同一个类型
// Stream.of(1,2,3,4).forEach(s->System.out.print(s));
// System.out.println();
// Stream.of("a","b","c","d").forEach(s->System.out.print(s));
String[] w={"a","b","c"};
//这样写其实是错误的,引用数据类型打印出来的是数据,基本数据类型打印出来的是地址值,会把基本数据类型当作一个元素放到Stream中
Stream.of(w).forEach(s->System.out.print(s));
}
}
名称 | 说明 |
---|---|
Stream |
过滤 |
Stream |
获取前几个元素 |
Stream |
跳过前几个元素 |
Stream |
元素去重,依赖hashCode 和equals 方法 |
static |
合并a 和b 两个流为一个流 |
Stream |
转换流中的数据类型 |
注意1: 中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据
过滤:可以加条件
package com.itheima.demo1;
import java.util.ArrayList;
import java.util.Collections;
public class StreamDemo6 {
public static void main(String[] args) {
// Stream filter(Predicate super T> predicate) 过滤
// Stream limit(long maxSize) 获取前几个元素
// Stream skip(long n) 跳过前几个元素
// Stream distinct() 元素去重,依赖hashCode和equals方法
// static Stream concat(Stream a, Stream b) 合并a和b两个流为一个流
// Stream map(Function mapper) 转换流中的数据类型
ArrayList list = new ArrayList<>();
Collections.addAll(list,"张无忌","周大力","张三丰","张三");
// filter 过滤 把姓张的留下来
// list.stream().filter(new Predicate() {
// @Override
// public boolean test(String s) {
//// 如果返回值为true表示当前数据留下来
//// 如果返回值为false表示当前数据舍弃不要
// return s.startsWith("张");
// }
// }).forEach(s->System.out.println(s));
// 改进:list.stream().filter(s->s.startsWith("张"))返回的是Stream流,中间方法返回的是Syteam流,中间方法返回后就会关闭,所以说建议使用链式方程,因为只使用一次
list.stream()
.filter(s->s.startsWith("张"))
.forEach(s->System.out.println(s));
System.out.println();
//可以看出来Stream流没有改变集合数据
System.out.println(list);
}
}
limit:限制前n个元素
skip:跳过前n个元素
package com.itheima.demo1;
import java.util.ArrayList;
import java.util.Collections;
public class StreamDemo7 {
public static void main(String[] args) {
// Stream limit(long maxSize) 获取前几个元素
// Stream skip(long n) 跳过前几个元素
ArrayList list = new ArrayList<>();
Collections.addAll(list,"张无忌","周大力","张三丰","张三","张良","王二麻子","谢广坤");
// limit 获取前几个元素
// skip 跳过前几个元素
// "张无忌","周大力","张三丰","张三","张良","王二麻子","谢广坤"
list.stream().limit(3)
.forEach(s -> System.out.println(s));//打印就知道就获取了前三个
System.out.println("");
list.stream().skip(4)
.forEach(s -> System.out.println(s));//跳过前三个,从第四个开始
System.out.println("");
list.stream().skip(2).limit(3).forEach(s -> System.out.println(s));
}
}
distinct 元素去重,依赖(hashcode和equqls方法)
concat 合并a和b两个流为一个流
package com.itheima.demo1;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;
public class StreamDemo8 {
public static void main(String[] args) {
// distinct 元素去重,依赖(hashcode和equqls方法)
// concat 合并a和b两个流为一个流
ArrayList list = new ArrayList<>();
Collections.addAll(list,"张无忌","张无忌","周大力","张三丰","张三","张良","王二麻子","谢广坤");
ArrayList list2 = new ArrayList<>();
Collections.addAll(list2,"燕知春","秦叮咚","楚天秋","齐夏");
//在这里是需要重写hashcode和equqls方法的不过String已经帮我们重写了
list.stream().distinct().forEach(s->System.out.println(s));
// concat 合并a和b两个流为一个流(数据类型必须一样)
Stream.concat(list.stream(),list2.stream()).distinct().forEach(s->System.out.println(s));
}
}
Stream
package com.itheima.demo1;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
public class StreamDemo9 {
public static void main(String[] args) {
// Stream map(Function mapper) 转换流中的数据类型
ArrayList list2 = new ArrayList<>();
Collections.addAll(list2,"燕知春-20","秦叮咚-21","楚天秋-24","齐夏-19");
// 需求:只获取里面的年龄并进行打印
// 下面的第一个类型是本来的,String
// 第二个是要转成的数据类型,Integer
//当map执行完毕后流上的数据就变成了整数
list2.stream().map(new Function() {
@Override
public Integer apply(String s) {
String[] split = s.split("-");
String age = split[1];
return Integer.parseInt(age);//转换成整数
}
}).forEach(s->System.out.println(s));
System.out.println();
list2.stream()
.map(s->Integer.parseInt(s.split("-")[1]))
.forEach(s->System.out.println(s));
}
}
名称 | 说明 |
---|---|
void forEach(Consumer action) |
对 Stream 中的每个元素执行指定的Consumer 动作,用于遍历流中的元素 。 |
long count() |
返回 Stream 中元素的数量,用于统计流中元素个数 。 |
toArray() |
将 Stream 中的元素收集起来,存储到一个数组中返回 。 |
collect(Collector collector) |
根据传入的Collector ,将 Stream 中的元素收集到对应的集合(如List 、Set 等)中 。 |
解释:
package com.itheima.demo1;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;
public class StreamDemo10 {
public static void main(String[] args) {
ArrayList list2 = new ArrayList<>();
Collections.addAll(list2,"燕知春-女-20","秦叮咚-女-21","楚天秋-男-24","齐夏-男-19");
// 收集List集合当中
// 需求:
// 我要把所有男性收集起来
// Consumer的泛型:表示流中数据的类型
// accept方法的形参s:表示流中的每个数据
// 方法体:对每一个数据的处理操作
// list2.stream().forEach(new Consumer() {
// @Override
// public void accept(String s) {
// System.out.println(s);
// }
// });
list2.stream().forEach(s->System.out.println(s));
// long count();统计数量
long count = list2.stream().count();
System.out.println(count);
System.out.println();
// toArray() 收集流中的数据,放到数组中
// Object[] arr=list2.stream().toArray();
// System.out.println(Arrays.toString(arr));
// 如果要放在指定的String类型中
// <>里面要放转换成的数据类型
// apply的形参:流中数据的个数,要跟数组的长度保持一致
// apply的返回值:具体类型的数组
// 方法体:就是创建数组
// toArray方法的参数的作用:负责创建一个指定类型的数组
// toarray方法的底层:依次得到流中的每个数据
// toArray方法的返回值:一个装着流中所有的数据的数组
String[] array = list2.stream().toArray(new IntFunction() {
@Override
public String[] apply(int value) {
return new String[value];
}
});
System.out.println(Arrays.toString(array));
// 修改Lambda
String[] arr2=list2.stream().toArray(value0->new String[value0]);
System.out.println(Arrays.toString(arr2));
}
}
可以把数据收集起来装到Collect里面的集合中
package com.itheima.demo1;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class StreamDemo11 {
public static void main(String[] args) {
ArrayList list2 = new ArrayList<>();
Collections.addAll(list2,"燕知春-女-20","秦叮咚-女-21","楚天秋-男-24","齐夏-男-19");
//收集起来装进list集合中
List collect = list2.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toList());
System.out.println(collect);
// 收集在map集合:
// 注意点:如果要收集多个数据到map集合中键不能重复
Map collect1 = list2.stream()
.filter(s -> "男".equals(s.split("-")[1]))
/***
* toMap :
* 参数一表示键的生成规则
* 参数二表示值的生成规则
* 参数一:
* Function
* 泛型一:表示流中每一个数据的类型
* 泛型二:表示 Map 集合中键的数据类型
* 方法:apply
* 形参:依次表示流里面的每一个数据
* 方法体:生成键的代码
* 返回值:已经生成的键
* 参数二:
* Function
* 泛型一:表示流中每一个数据的类型
* 泛型二:表示 Map 集合中值的数据类型
* 方法:apply
* 形参:依次表示流里面的每一个数据
* 方法体:生成值的代码
* 返回值:已经生成的值
*/
.collect(Collectors.toMap(new Function() {
@Override
//第一个Strting表示返回的数据,第二个表示流里面的数据(要转到map集合中)
public String apply(String s) {
return s.split("-")[0];
}
}, new Function() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s.split("-")[2]);
}
}));
System.out.println(collect1);
list2.stream()
.filter(s->"男".equals(s.split("-")[1]))
.collect(Collectors.toMap(s->s.split("-")[0],s-> Integer.parseInt(s.split("-")[2])));
}
}