Stream流
Stream流算是Java简化步骤的最基础部分
Stream流通过和Lambda,方法引用,函数式常用接口等相结合,简化数据的存放,筛选和输出
Stream流的使用
Stream流的使用分为三个步骤:
- 生成流
- 通过数据源(集合,数组)生成流
- 例如:list.stream()
- 中间操作
- 一个流后面可以跟零个或无限个中间操作,其目的是打开流做出某种程度的过滤或映射,然后返回一个新的流
- 例如:filter()
- 终结操作
- 一个流只能有一个终结操作,操作执行后,流被使用,无法再被操作
- 例如:forEach()
下面我们先给出一个Stream流的使用案例
需求:
- 我们想在下列集合中得到姓刘且长度为2的名字并输出
代码如下:
代码语言:javascript复制import java.util.ArrayList;
import java.util.stream.Stream;
public class Demo1 {
public static void main(String[] args) {
//首先创造集合
ArrayList<String> arr = new ArrayList<>();
//加入对象
arr.add("刘禅");
arr.add("刘备");
arr.add("孙尚香");
arr.add("诸葛亮");
arr.add("刘亦菲");
//我们的要求是从arr中取出姓刘且两个字的名字
//如果我们采用正常方法,需要采用到for循环一次一次遍历
//这里我们直接给出stream流方法(注意:Stream流方法通常与Lambda以及方法引用实现)
arr.stream().filter(s -> s.startsWith("刘")).filter(s -> s.length() == 2).forEach(System.out::println);
}
}
Stream流的生成方法
Stream流常见生成方法:
- Collection体系的集合可以使用默认方法Stream()生成流
- Map体系的集合只能够间接的生成流
- 数组只能通过Stream类的固定of方法生成流
下面给出示例代码:
代码语言:javascript复制import java.util.*;
import java.util.stream.Stream;
public class Demo2 {
public static void main(String[] args) {
//Collection集合生成Stream流可直接生成
List<String> list = new ArrayList<>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<>();
Stream<String> setStream = set.stream();
//Map集合生成Stream流需要间接生产
Map<String,Integer> map = new HashMap<>();
Stream<String> KeyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String,Integer>> mapStream = map.entrySet().stream();
//数组需要通过Stream的Static方法of来生产流
String[] strArray = {"Hello","World","Java"};
Stream<String> strStream = Stream.of(strArray);
Stream<Integer> intStream = Stream.of(10,20,30);
}
}
Stream流的中间操作方法
大致方法如下:
方法名 | 说明 |
---|---|
Stream filter(Predicate predicate) | 用于对流中的数据进行过滤 |
Stream limit(long maxSize) | 返回此流中的元素组成的流,截取前指定参数个数的数据 |
Stream skip(long n) | 跳过指定参数个数的数据,返回由该流的剩余元素组成的流 |
static Stream concat(Stream a,Stream b) | 合并a和b两个流组成一个流 |
Stream distinct() | 返回该流的不同元素组成的流 |
Stream sorted() | 返回由此流的元素组成的流,按照自然顺序排序 |
Stream sorted(Comparator comparator) | 返回由此流的元素组成的流,按照Comparator要求排序 |
Stream map(Function mapper) | 返回由给定函数应用于此类的元素的结果组成的流 |
IntStream Stream mapToInt(Function mapper) | 返回一个IntStream其中包含将给定函数应用于此流的元素的结果 |
下面给出上述方法的示例代码:
代码语言:javascript复制import java.util.ArrayList;
import java.util.stream.Stream;
public class Demo3 {
public static void main(String[] args) {
//首先创造集合
ArrayList<String> arr = new ArrayList<>();
//加入对象
arr.add("刘禅");
arr.add("刘备");
arr.add("孙尚香");
arr.add("诸葛亮");
arr.add("刘亦菲");
//以下是filter方法讲解
//获得所有姓刘的集合并输出
arr.stream().filter((String s) -> s.startsWith("刘")).forEach(System.out::println);
System.out.println("-----------");
//获得所有三个字的名字的集合并输出
arr.stream().filter((String s) -> s.length() == 3).forEach(System.out::println);
System.out.println("-----------");
//获得所有姓刘的且名字是三个字的集合并输出
arr.stream().filter(s -> s.startsWith("刘")).filter(s -> s.length() == 2).forEach(System.out::println);
System.out.println("-----------");
//以下是limit和skip方法讲解
//我们只要前两个名字输出
arr.stream().limit(2).forEach(System.out::println);
System.out.println("-----------");
//我们跳过前两个名字输出
arr.stream().skip(2).forEach(System.out::println);
System.out.println("-----------");
//我们跳过前两个名字然后输出两个名字
arr.stream().skip(2).limit(2).forEach(System.out::println);
System.out.println("-----------");
//以下是concat和distinct方法的讲解
//concat是static方法,我们需要两个Stream流对象
Stream<String> s1 = arr.stream().limit(4);
Stream<String> s2 = arr.stream().skip(2);
Stream<String> s3 = arr.stream().skip(3);
//然后我们调用concat方法,要由Stream类调用
//Stream.concat(s1,s2).forEach(System.out::println);
//System.out.println("-----------");
//因为我们concat方法中获得的元素有重复元素,我们需要用distinct方法去除
Stream.concat(s1,s3).distinct().forEach(System.out::println);
System.out.println("-----------");
}
}
代码语言:javascript复制import java.util.ArrayList;
public class Demo4 {
public static void main(String[] args) {
//首先创造集合
ArrayList<String> arr = new ArrayList<>();
//我们因为演示sorted()方法,所有这里数据采用拼音
arr.add("zhangchen");
arr.add("zhangmanyu");
arr.add("liudehuada");
arr.add("sunce");
arr.add("daqiao");
//首先我们尝试自然排序
arr.stream().sorted().forEach(System.out::println);
System.out.println("-----------");
//然后我们按照长度排序(注意:这里仅仅按照长度排序,当长度相同时其他数据随机排序)
arr.stream().sorted((s1,s2) -> s1.length()-s2.length()).forEach(System.out::println);
System.out.println("-----------");
//我们创造一个按长度排序,当长度相同时,我们按自然排序
arr.stream().sorted((s1,s2) -> {
int num = s1.length()-s2.length();
int num2 = num==0?s1.compareTo(s2):num;
return num2;
}).forEach(System.out::println);
System.out.println("-----------");
}
}
代码语言:javascript复制import java.util.ArrayList;
public class Demo5 {
public static void main(String[] args) {
//首先创造集合
ArrayList<String> arr = new ArrayList<>();
//我们添加元素
arr.add("10");
arr.add("20");
arr.add("30");
arr.add("40");
arr.add("50");
//我们采用map方法转换类型并输出
arr.stream().map((String s) -> Integer.parseInt(s)).forEach(System.out::println);
System.out.println("---------");
//我们也可以采用mapToInt方法转换
arr.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
System.out.println("---------");
//mapToInt方法中可以采用sum()方法获得总和
int sum = arr.stream().mapToInt(Integer::parseInt).sum();
System.out.println(sum);
System.out.println("---------");
}
}
Stream流的终结操作方法
大致方法如下:
方法名 | 说明 |
---|---|
void forEach(Consumer action) | 对此流的每个元素执行操作 |
long count() | 返回此流中的元素数 |
下面给出示例代码:
代码语言:javascript复制import java.util.ArrayList;
public class Demo6 {
public static void main(String[] args) {
//首先创造集合
ArrayList<String> arr = new ArrayList<>();
//加入对象
arr.add("刘禅");
arr.add("刘备");
arr.add("孙尚香");
arr.add("诸葛亮");
arr.add("刘亦菲");
//我们直接测试输出
arr.stream().forEach(System.out::println);
//我们统计姓刘的人数
long num = arr.stream().filter(s -> s.startsWith("刘")).count();
System.out.println(num);
}
}
Stream流收集操作
对数据使用Stream方法变成流后,我们该如何回收到集合中呢?
Java提供给了我们collect方法:
- R collect(Collector collector)
- 但这个收集方法的参数是一个接口
工具类Collectiors提供了具体的收集方法:
- public static Collector toList():把元素收集到List集合中
- public static Collector toSet():把元素收集到Set集合中
- public static Collector toMap(Function keyMapper,Function valueMapper):把元素收集到Map集合中
下面给出示例代码:
代码语言:javascript复制import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Demo1 {
public static void main(String[] args) {
//创造集合1
ArrayList<String> arrayList1 = new ArrayList<>();
arrayList1.add("bandecan");
arrayList1.add("heimao");
arrayList1.add("miluo");
arrayList1.add("mikumaster");
//针对集合1获得长度大于6的names
Stream<String> stream1 = arrayList1.stream().filter(s -> s.length()>6);
//把stream1的数据转换为List集合
List<String> List1 = stream1.collect(Collectors.toList());
for(String s : List1){
System.out.println(s);
}
//创造集合2
Set<Integer> set = new HashSet<>();
set.add(25);
set.add(20);
set.add(30);
set.add(35);
//针对集合2获得年龄大于28的ages
Stream<Integer> stream2 = set.stream().filter(age -> age > 28);
//把Stream2的数据转化为Set集合
Set<Integer> ages = stream2.collect(Collectors.toSet());
for (int age : ages){
System.out.println(age);
}
//创造集合3
String[] strArrays = {"胡桃,20","可莉,10","钟离,25"};
//针对集合3获得年龄大于18的String
Stream<String> stream3 = Stream.of(strArrays).filter(s -> Integer.parseInt(s.split(",")[1])>18);
//把stream3的数据转化为Map集合
Map<String,Integer> map = stream3.collect(Collectors.toMap((String s) -> s.split(",")[0], (String s) -> Integer.parseInt(s.split(",")[1])));
Set<String> keySet = map.keySet();
for(String key : keySet){
System.out.println(key ":" map.get(key));
}
}
}
案例:Stream流的练习
条件:
- 我们给出两个ArrayList集合,分别储存6名男生,6名女生的名称
- 我们给出学生类Actor,里面有name和构造方法
需求:
- 男生只要名字为3个字的前三人
- 女生只要姓小的,且不要第一个
- 把过滤后的男生女生合并到一起
- 把合并后的名字做参数创造学生类对象并输出
下面给出示例代码:
代码语言:javascript复制import java.util.ArrayList;
import java.util.stream.Stream;
public class ActorDemo {
public static void main(String[] args) {
//我们创建集合
ArrayList<String> manList = new ArrayList<>();
manList.add("黑猫子");
manList.add("米洛");
manList.add("白的肾");
manList.add("昂扣挼的");
manList.add("卡慕瓜");
manList.add("与山鸭");
ArrayList<String> womanList = new ArrayList<>();
womanList.add("哈娜");
womanList.add("小卷");
womanList.add("小卡");
womanList.add("子音");
womanList.add("小沐");
womanList.add("米神");
//第一步:男演员只要名字为三个字的前三人
Stream<String> manListSelect = manList.stream().filter(s -> s.length() == 3).limit(3);
//第二步:女演员只要姓小的且不要第一个
Stream<String> womanListSelect = womanList.stream().filter(s -> s.startsWith("小")).skip(1);
//第三步:将两个合并在一起
Stream<String> lastList = Stream.concat(manListSelect, womanListSelect);
//第四步:把上一步所有元素参数创造对象并遍历
lastList.forEach(s -> {
Actor actor = new Actor(s);
System.out.println(actor.name);
});
}
}
代码语言:javascript复制public class Actor {
public String name;
public Actor(String name){
this.name = name;
}
}
结束语
好的,关于Stream流我们就讲解到这里