1.Stream流体验
import java.util.ArrayList;
public class StreamDemo {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("张三");
list.add("张曼玉");
list.add("王祖贤");
list.add("张三丰");
list.add("张敏");
list.add("张无忌");
//把集合中所有以"张"开头的元素存储到一个新的集合
ArrayList<String> zhangList = new ArrayList<String>();
for(String s : list) {
if(s.startsWith("张")) {
zhangList.add(s);
}
}
// System.out.println(zhangList);
//把"张"开头的集合中的长度为3的元素存储到一个新的集合
ArrayList<String> threeList = new ArrayList<String>();
for(String s : zhangList) {
if(s.length() == 3) {
threeList.add(s);
}
}
// System.out.println(threeList);
//遍历上一步得到的集合
for(String s : threeList) {
System.out.println(s);
}
System.out.println("--------");
//Stream流来改进
// list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
}
}
使用Stream流的方式完成过滤操作
list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3);
直接阅读代码的字面意思即可完美展示无关逻辑方式的语义: 生成流、过滤姓张、过滤长度为3、逐一打印
Stream流把真正的函数式编程风格引入到Java中
2.Stream流的生成方法
方法名 | 说明 |
---|---|
list.stream() | 生成流:通过数据源(集合,数组等)生成流 |
filter() | 中间操作:一个流后面可以跟随零个或多个中间操作, 其目的主要是打开流,做出某种程度的数据过滤映射,然后返回一个新的流,交给下一个操作使用 |
forEach() | 终结操作:一个流只能有一个终结操作,当这个操作执行后,流就被使用“光" 了,无法再被操作。所以这必定是流的最后一个操作 |
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.stream.Stream;
public class MyStream {
public static void main(String[] args) {
//单列集合
ArrayList<String> list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
//Stream<String> stream=list.stream();
//stream.forEach(s->System.out.println(s));
list.stream().forEach(s->System.out.println(s));
/* aaa
bbb
ccc*/
System.out.println("===========");
//双列集合
HashMap<String,Integer> hm=new HashMap<>();
hm.put("zhangsan",23);
hm.put("lisi",24);
hm.put("wangwu",25);
hm.put("zhaoliu",26);
hm.put("qianqi",27);
//双列集合不能直接获取Stream流,有两种方法
//KeySet
//先获取到所有键
//再把这个set集合中所有的键放到Stream流中
hm.keySet().stream().forEach(s->System.out.println(s));
/*lisi
qianqi
zhaoliu
zhangsan
wangwu*/
System.out.println("===========");
//entrySet
//先获取到生源地键值对对象
//再把这个Set集合中所有的键值对对象放到Stream流中
hm.entrySet().stream().forEach(s->System.out.println(s));
/*lisi=24
qianqi=27
zhaoliu=26
zhangsan=23
wangwu=25*/
System.out.println("===========");
//数组
int[] arr={1,2,3,4,5};
Arrays.stream(arr).forEach(s->System.out.println(s));
System.out.println("===========");
//同种数据类型的多个数据
Stream.of(1,2,3,4,5,6,7,8).forEach(s->System.out.println(s));
}
}
3.Stream流的中间操作方法
中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作。
方法名 | 说明 |
---|---|
Stream filter(Predicate predicate) | 用于对流中的数据进行过滤 |
Stream limit(long maxSize) | 返回此流中的元素组成的流,截取前指定参数个数的数据 |
Stream skip(long n) | 跳过指定参数个数的数据,返回由该流的剩余元素组成的流 |
static Stream concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
Stream distinct() | 返回由该流的不同元素(根据Object.equals(Object) )组成的流 |
Stream sorted() | 返回由此流的元素组成的流,根据自然顺序排序 |
Stream sorted(Comparator comparator) | 返回由该流的元素组成的流,根据提供的Comparator进行排序 |
Stream map(Function mapper) | 返回由给定函数应用于此流的元素的结果组成的流 |
IntStream mapToInt(ToIntFunction mapper) | 返回一个IntStream其中包含将给定函数应用于此流的元素的结 |
filter
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
//创建一个集合存储多个元素
ArrayList<String> list = new ArrayList<>();
list.add("小黑");
list.add("张无忌");
list.add("大熊猫");
list.add("张三峰");
list.add("小白");
list.add("张飞");
//需要1:把list集合中以张开头的在控制台输出
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
System.out.println("--------");
// 张无忌
// 张三峰
// 张飞
//需要2:把list集合中长度为3的元素输出
list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
System.out.println("--------");
// 张无忌
// 大熊猫
// 张三峰
//需求3:把以张开头,长度为3的在控制台输出
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
// 张无忌
// 张三峰
}
}
limit 和 skip
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
//创建一个集合存储多个元素
ArrayList<String> list = new ArrayList<>();
list.add("小黑");
list.add("张无忌");
list.add("大熊猫");
list.add("张三峰");
list.add("小白");
list.add("张飞");
//需要1:取前三个数据在控制台输出
list.stream().limit(3).forEach(System.out::println);
System.out.println("---------");
// 小黑
// 张无忌
// 大熊猫
//需求2:跳过3个元素,把剩下的在控制台输出
list.stream().skip(3).forEach(System.out::println);
System.out.println("---------");
// 张三峰
// 小白
// 张飞
//需求3:跳过2个元素,把剩下元素的前两个输出
list.stream().skip(2).limit(2).forEach(System.out::println);
// 大熊猫
// 张三峰
}
}
concat 和 distinct
import java.util.ArrayList;
import java.util.stream.Stream;
public class Demo {
public static void main(String[] args) {
//创建一个集合存储多个元素
ArrayList<String> list = new ArrayList<>();
list.add("小黑");
list.add("张无忌");
list.add("大熊猫");
list.add("张三峰");
list.add("小白");
list.add("张飞");
//需要1:取前4个数据组成一个流
Stream<String> s1 = list.stream().limit(4);
//需求2:跳过2个数据组成一个流
Stream<String> s2 = list.stream().skip(2);
//需求3:合并1,2结果得到的流,并输出
// Stream.concat(s1,s2).forEach(System.out::println);
// 小黑
// 张无忌
// 大熊猫
// 张三峰
// 大熊猫
// 张三峰
// 小白
// 张飞
//需求4:合并1,2结果得到的流,并输出,要求结果不重复
Stream.concat(s1, s2).distinct().forEach(System.out::println);
// 小黑
// 张无忌
// 大熊猫
// 张三峰
// 小白
// 张飞
}
}
sorted()和sorted(Comparator comparator)
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
//创建一个集合存储多个元素
ArrayList<String> list = new ArrayList<>();
list.add("b123");
list.add("a1");
list.add("f1234");
list.add("c12");
list.add("e12345");
list.add("d12345");
//需要1:按照字母顺序在控制台输出
list.stream().sorted().forEach(System.out::println);
// a1
// b123
// c12
// d12345
// e12345
// f1234
//需求2:按照字符串长度,长度相同自然排序
list.stream().sorted((s1, s2) -> {
int num1 = s1.length() - s2.length();
int num2 = num1 == 0 ? s1.compareTo(s2) : num1;
return num2;
}).forEach(System.out::println);
// a1
// c12
// b123
// f1234
// d12345
// e12345
}
}
map 和 mapToInt
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
//创建一个集合存储多个元素
ArrayList<String> list = new ArrayList<>();
list.add("10");
list.add("20");
list.add("30");
list.add("40");
list.add("50");
//需要:将集合中的字符串转换为整数后在控制台输出
// list.stream().map(s->Integer.parseInt(s)).forEach(System.out::println);
//方法引用
// list.stream().map(Integer::parseInt).forEach(System.out::println);
// list.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
// 10
// 20
// 30
// 40
// 50
//InStream中方法 :int sum()返回流中元素总和
int result = list.stream().mapToInt(Integer::parseInt).sum();
System.out.println(result); //150
}
}
4.Stream流的终结操作方法
终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作。
方法名 | 说明 |
---|---|
void forEach(Consumer action) | 对此流的每个元素执行操作,Consumer接口中的方法——void accept(T t)对给定的参数执行此操作 |
long count() | 返回此流中的元素数 |
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
//创建一个集合存储多个元素
ArrayList<String> list = new ArrayList<>();
list.add("小黑");
list.add("张三忌");
list.add("大熊猫");
list.add("张天峰");
list.add("小白");
list.add("张飞");
//需求1:输出集合中的元素
list.stream().forEach(System.out::println);
// 小黑
// 张无忌
// 大熊猫
// 张三峰
// 小白
// 张飞
//需求2:统计以张开头的个数
long count = list.stream().filter(s -> s.startsWith("张")).count();
System.out.println(count); //3
}
}
5.Stream流的收集操作
附加:在Stream流中无法直接修改集合,数组等数据源中的数据,修改的是流上的数据
Stream流的收集方法
方法名 | 说明 |
---|---|
R collect(Collector collector) | 但是这个收集方法的参数是一个Collector 接口 |
工具类Collectors提供了具体的收集方式
方法名 | 说明 |
---|---|
public static Collector toList() | 把元素收集到List集合中 |
public static Collector toSet() | 把元素收集到Set集合中 |
public static Collector toMap(Function keyMapper,Function valueMapper) | 把元素收集到Map集合中 |
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Demo {
public static void main(String[] args) {
//创建list集合存储多个元素
ArrayList<String> list = new ArrayList<>();
list.add("小黑");
list.add("大熊猫");
list.add("张飞");
list.add("小熊猫");
//需求1:得到名字为三个字的流
Stream<String> listStream = list.stream().filter(name -> name.length() == 3);
//需求2:把使用Stream操作得到数据存入list集合并遍历
List<String> names = listStream.collect(Collectors.toList());
for (String name : names) {
System.out.println(name);
// 大熊猫
// 小熊猫
}
//创建Set集合对象
Set<Integer> set = new HashSet<>();
set.add(10);
set.add(20);
set.add(30);
set.add(40);
//需求3:得到年龄大于25的流
Stream<Integer> setStream = set.stream().filter(age -> age > 25);
//需求4:把使用Stream操作得到数据存入set集合并遍历
Set<Integer> ages = setStream.collect(Collectors.toSet());
for (Integer age : ages) {
System.out.println(age);
// 40
// 30
}
//定义个字符串数组,由姓名和年龄组成
String[] strArray = {"小黑,10", "小白,20", "小熊猫,30", "大熊猫,40"};
//需求5:得到字符串数组中年龄大于25的流
Stream<String> arrayStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);
//需求6:把使用Stream操作得到数据存入map集合并遍历,姓名做键,年龄做值
Map<String, Integer> map = arrayStream.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
Set<String> keySet = map.keySet();
for (String key : keySet) {
Integer vlaue = map.get(key);
System.out.println(key + "," + vlaue);
// 大熊猫,40
// 小熊猫,30
}
}
}
练习:
演员类:
public class Actor {
private String name;
public Actor(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Actor{" +
"name='" + name + '\'' +
'}';
}
}
测试类:
import java.util.ArrayList;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
//创建集合
ArrayList<String> manList = new ArrayList<String>();
manList.add("张国立");
manList.add("张晋");
manList.add("刘烨");
manList.add("郑伊健");
manList.add("徐峥");
manList.add("王宝强");
ArrayList<String> womanList = new ArrayList<String>();
womanList.add("郑爽");
womanList.add("杨幂");
womanList.add("关晓彤");
womanList.add("张天爱");
womanList.add("杨幂");
womanList.add("赵丽颖");
/*
//男演员只要名字为3个字的前两人
Stream<String> stream1 = manList.stream().filter(s -> s.length() == 3).limit(2);
//女演员只要姓杨的,并且不要第一个
Stream<String> stream2 = womanList.stream().filter(s -> s.startsWith("杨")).skip(1);
//把过滤后的男演员姓名和女演员姓名合并到一起
Stream<String> stream = Stream.concat(stream1, stream2);
//把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
// stream.map(Actor::new).forEach(System.out::println);
stream.map(Actor::new).forEach(p -> System.out.println(p.getName()));
*/
Stream.concat(manList.stream().filter(s -> s.length() == 3).limit(2),
womanList.stream().filter(s -> s.startsWith("杨")).skip(1)).map(Actor::new).
forEach(p -> System.out.println(p.getName()));
}
}