Stream流概述
Stream流:相当于把要操作的的数据放到流水线上进行各种操作。
Stream流的作用:结合Lambda表达式,简化集合,数组的操作
Stream流一般采用链式编程+Lambda表达式写。
使用步骤:
-
先得到一条Stream流,并把数据放上去
-
利用Stream流中的API进行各种操作
过滤,转换,统计,打印等操作
这些方法可分为:中间方法和终结方法
中间方法:方法调用完毕后,还可调用其他方法。比如过滤
终结方法:方法调用完毕后,不能调用其他方法了,比如输出打印
Stream流使用
- 获取Stream流对象
获取方式 | 方法名 | 说明 |
---|---|---|
Collection单列集合 | default Stream |
Collection中的默认方法 |
Map双列集合 | 无 | 无法直接使用stream流 |
数组 | public static |
Arrays工具类中的静态方法 |
一堆零散的数据 | public static |
Stream接口中的静态方法,T...Value是可变参数 |
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args) {
//1.Collection单列集合创建Stream流
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"a","b","c","d");
list.stream().forEach(s-> System.out.println(s));//其中list.stream()就已经获取了stream流对象了
//.forEach是Stream流中的终结方法
//2.Map集合创建Stream流
HashMap<String,String> map=new HashMap<>();
map.put("a","A");
map.put("b","B");
map.put("c","C");
map.keySet().stream()
.forEach(s-> System.out.println(s+"="+map.get(s)));//这段是Stream流的方法
map.entrySet().stream()
.forEach(s-> System.out.println(s.getKey()+"="+s.getValue()));//这段是Stream流的方法
//3.数组获取Stream流
int[] numbers=new int[]{1,2,3,4,5};
Arrays.stream(numbers)
.forEach(n-> System.out.println(n));//这段是Stream流的方法
//4.一堆零散的数据获取Stream流(必须是相同数据类型)
Stream.of(1,2,3,4,5)
.forEach(n-> System.out.println(n));//这段是Stream流的方法
}
}
- Stream流的中间方法
方法名 | 说明 |
---|---|
Stream |
过滤 |
Stream |
获取前几个元素 |
Stream |
跳过前几个元素 |
Stream |
元素去重(依赖hashCode和equals方法) |
static Stream |
合并a和b两个流为一个流 |
Stream |
转换流中的数据类型 |
注意:
- 中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议采用链式编程。
- 修改Stream流中的数据,不会影响到原数组或集合中的数据
- filter过滤方法中的参数是一个函数式接口,使用Lambda表达式即可
- map中的参数也是一个函数式接口,需要使用Lambda表达式简化
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;
public class Main {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"1","2","3","11","22","33","111","222","333");
//filter方法详解
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length()==1;//s表示流中每一个数据,如果返回值为true表示留下数据,false表示不留下数据
}
}).forEach(s-> System.out.println(s));
//简化版filter
list.stream()
.filter(s->s.length()==1)//过滤,只留下长度为1的数据
.forEach(s-> System.out.println(s));//遍历输出结过:1,2,3
list.stream()
.limit(4)//获取前4个元素
.forEach(s-> System.out.println(s)); //遍历结果:1,2,3,11
list.stream()
.skip(4)//跳过前4个元素
.forEach(s-> System.out.println(s));//遍历结果:"22","33","111","222","333"
list.add("1");
list.stream()
.distinct()//去重
.forEach(s-> System.out.println(s));//遍历
ArrayList<String> list2=new ArrayList<>();
Collections.addAll(list,"a","b","c","d","e");
Stream.concat(list.stream(),list2.stream())//利用Stream流中静态方法发将两个小流合并为一条大流
.forEach(s-> System.out.println(s));
list.stream()
.map(s-> Integer.parseInt(s))//将原本的数据类型转化为Int类型
.forEach(s-> System.out.println(s));
//map方法详细写法
list.stream().map(new Function<String, Integer>() {//第一个泛型是数据原本的类型,第二个泛型是要转化的类型
@Override
public Integer apply(String s) {//这个s表示流里面每一个数据
return Integer.parseInt(s);
}
}).forEach(s-> System.out.println(s)); //在这里的forEatch中s就是整数类型了
}
}
- Stream流中的终结方法
方法名 | 说明 |
---|---|
void forEach(Consumer action) | 遍历 |
long count() | 统计 |
toArray(IntFunction<> function) | 收集流中数据,放到数组中 |
collect(Collector collector) | 收集流中数据,放到集合中 |
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"1","2","3","11","22","33","111","222","333");
list.stream().forEach(s-> System.out.println(s));//遍历,这玩意是个函数式接口,方法和集合的forEach是一模一样
long count = list.stream().count();//统计流中数据个数
System.out.println(count);
//toArray方法详写
list.stream().toArray(new IntFunction<String[]>() {//IntFunction泛型:具体转化为什么数组
@Override
public String[] apply(int value) {//value流中数据的个数
return new String[value];//方法体:创建数组
}//返回值:具体的数组
});
//Lambda表达式简化
list.stream().toArray(value->new String[value]);
//collect方法(可以收集流中数据并放到集合中,可以放到List,Set,Map)
//1.收集到List集合中(实际创建的是ArrayList)
List<String> newList = list.stream()//收集到list集合中
.filter(s -> s.length() == 2)
.collect(Collectors.toList());//Collectors是Stream接口中的工具类,toList是工具类中的方法
System.out.println(newList);
//2.收集到Set中(实际创建的是HashSet)
Set<String> newSet = list.stream()//注意Set集合特性,无重复元素!!
.limit(3)
.collect(Collectors.toSet());
System.out.println(newSet);
}
}
收集到map集合
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3", "11", "22", "33", "111", "222", "333");
/*
*这里的toMap(键的生成规则,值生成的规则)
*在第一个Function里面第一个泛型:流中数据类型,第二个泛型:map集合中键的数据类型
*apply形参:依次表示流中每个数据
*方法体:生成键的代码
*返回值:已经生成的键
*注意map的键不能重复!
*
*在第二个Function里面第一个泛型:流中数据类型,第二个泛型:map集合中值的数据类型
*apply形参:依次表示流中每个数据
*方法体:生成键的代码
*返回值:已经生成值
*/
Map<String, Integer> map = list.stream()
.filter(s -> s.length() == 3)
.collect(Collectors.toMap(new Function<String, String>() {
@Override
public String apply(String s) {
return s.substring(0, 1);
}
}, new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s.substring(2));
}
}));
System.out.println(map);
//简化!
Map<String, Integer> map = list.stream()
.filter(s -> s.length() == 3)
.collect(Collectors.toMap(s-> s.substring(0, 1), s->Integer.parseInt(s.substring(2))));
}
}