Stream流
比较
普通的for循环,遍历筛选
package com.itheima.demo01.Stream;
import java.util.ArrayList;
import java.util.List;
public class Demo01List {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//对list集合中的元素进行过滤,只要以张开头的元素,存储到一个新的集合中
List<String> listA = new ArrayList<>();
for (String s : list) {
if (s.startsWith("张")) {
listA.add(s);
}
}
//对listA集合进行过滤,只要姓名长度为3的人,存储到一个新集合中
List<String> listB = new ArrayList<>();
for (String s : listA) {
if (s.length() == 3) {
listB.add(s);
}
}
//遍历listB集合
for (String s : listB) {
System.out.println(s);
}
}
}
运行结果
张无忌
张三丰
Stream流过滤输出
package com.itheima.demo01.Stream;
import java.util.ArrayList;
import java.util.List;
public class Demo02Stream {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
list.stream()
.filter(name -> name.startsWith("张"))
.filter(name -> name.length() == 3)
.forEach(name -> System.out.println(name));
}
}
运行结果
张无忌
张三丰
获取Stream
默认方法
静态方法
package com.itheima.demo02.Stream;
import java.util.*;
import java.util.stream.Stream;
public class Demo01GetStream {
public static void main(String[] args) {
//将list转换为流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
//将set转换为流
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
//将map中的key转换为流
Map<String, String> map = new HashMap<>();
Set<String> keySet = map.keySet();
Stream<String> stream3 = keySet.stream();
//将map中的value转换为流
Collection<String> values = map.values();
Stream<String> stream4 = values.stream();
//将map中的k-v转换为流
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
//把数组转换为Stream流
Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);
Integer[] arr = {1, 2, 3, 4, 5};
Stream<Integer> stream7 = Stream.of(arr);
}
}
Stream流中的常用方法
流模型的操作很丰富,这里介绍一些常用的API。这些方法可以被分成两种:
- 延迟方法:返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为延迟方法。)
- 终结方法:返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder那样的链式调用。本小节中,终结方法包括
count
和forEach
方法。
只要当前流没有调用终结方法,就可以继续使用延迟方法
遍历——void forEach(Consumer<? super T> action);
Consumer
唯一的抽象方法void accept(T t);
,将数据一个一个进行消费
package com.itheima.demo02.Stream;
import java.util.stream.Stream;
public class Demo02Stream_forEach {
public static void main(String[] args) {
Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六", "田七");
stream.forEach(name -> System.out.println(name));
}
}
运行结果
张三
李四
王五
赵六
田七
过滤——Stream filter(Predicate<? super T> predicate);
Predicate
唯一的抽象方法boolean test(T t);
,利用条件进行筛选
package com.itheima.demo02.Stream;
import java.util.stream.Stream;
public class Demo03Stream_filter {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
Stream<String> stream2 = stream1.filter((String name)->name.startsWith("张"));
//Stream流只能消费一次,调用完毕后转到下一个Stream流,源数据被销毁
stream2.forEach(name-> System.out.println(name));
}
}
运行结果
张三丰
张翠山
张无忌
映射—— Stream map(Function<? super T, ? extends R> mapper);
Function
唯一的抽象方法R apply(T t);
,建立一一映射的关系
package com.itheima.demo02.Stream;
import java.util.stream.Stream;
public class Demo04Stream_map {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("1", "2", "3", "4");
Stream<Integer> stream2 = stream1.map((String s) -> Integer.parseInt(s));
stream2.forEach(i -> System.out.println(i));
}
}
运行结果
1
2
3
4
计数——long count();
package com.itheima.demo02.Stream;
import java.util.ArrayList;
import java.util.stream.Stream;
public class Demo05Stream_count {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
Stream<Integer> stream = list.stream();
long count = stream.count();
System.out.println(count);
}
}
运行结果
7
截取——Stream limit(long maxSize);
package com.itheima.demo02.Stream;
import java.util.stream.Stream;
public class Demo06Stream_limit {
public static void main(String[] args) {
String[] arr = {"美羊羊", "喜洋洋", "懒洋洋", "灰太狼", "红太狼"};
Stream<String> stream1 = Stream.of(arr);
stream1.limit(3).forEach(name -> System.out.println(name));
}
}
运行结果
美羊羊
喜洋洋
懒洋洋
跳过——Stream skip(long n);
package com.itheima.demo02.Stream;
import java.util.stream.Stream;
public class Demo07Stream_skip {
public static void main(String[] args) {
String[] arr = {"美羊羊", "喜洋洋", "懒洋洋", "灰太狼", "红太狼"};
Stream<String> stream1 = Stream.of(arr);
stream1.skip(3).forEach(name -> System.out.println(name));
}
}
运行结果
灰太狼
红太狼
合并—— public static Stream concat(Stream<? extends T> a, Stream<? extends T> b)
package com.itheima.demo02.Stream;
import java.util.stream.Stream;
public class Demo08Stream_concat {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
Stream<String> stream2 = Stream.of("美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼");
Stream<String> concat = Stream.concat(stream1, stream2);
concat.forEach(name-> System.out.println(name));
}
}
运行结果
张三丰
张翠山
赵敏
周芷若
张无忌
美羊羊
喜洋洋
懒洋洋
灰太狼
红太狼
练习:集合元素处理
练习:集合元素处理(传统方式)
现在有两个ArrayList集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
5. 将两个队伍合并为一个队伍;存储到一个新集合中。
6. 根据姓名创建Person对象;存储到一个新集合中。
7. 打印整个队伍的Person对象信息。
Person类
package com.itheima.demo03.Stream;
public class Person {
private String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
传统
package com.itheima.demo03.Stream;
import java.util.ArrayList;
public class Demo01StreamTest {
public static void main(String[] args) {
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
one.add("老子");
one.add("庄子");
one.add("洪七公");
//1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
ArrayList<String> one1 = new ArrayList<>();
for (String name : one) {
if (name.length() == 3) {
one1.add(name);
}
}
//2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
ArrayList<String> one2 = new ArrayList<>();
for (int i = 0; i < 3; i++) {
one2.add(one1.get(i));//i = 0,1,2
}
//第二支队伍
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("尼古拉斯赵四");
two.add("张天爱");
two.add("张二狗");
//3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
ArrayList<String> two1 = new ArrayList<>();
for (String name : two) {
if (name.startsWith("张")) {
two1.add(name);
}
}
//4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
ArrayList<String> two2 = new ArrayList<>();
for (int i = 2; i < two1.size(); i++) {
two2.add(two1.get(i)); //i 不包含0 1
}
//5. 将两个队伍合并为一个队伍;存储到一个新集合中。
ArrayList<String> all = new ArrayList<>();
all.addAll(one2);
all.addAll(two2);
//6. 根据姓名创建Person对象;存储到一个新集合中。
ArrayList<Person> list = new ArrayList<>();
for (String name : all) {
list.add(new Person(name));
}
//7. 打印整个队伍的Person对象信息。
for (Person person : list) {
System.out.println(person);
}
}
}
运行结果
Person{name=‘宋远桥’}
Person{name=‘苏星河’}
Person{name=‘石破天’}
Person{name=‘张天爱’}
Person{name=‘张二狗’}
Stream
package com.itheima.demo03.Stream;
import java.util.ArrayList;
import java.util.stream.Stream;
/*
练习:集合元素处理(Stream方式)
将上一题当中的传统for循环写法更换为Stream流式处理方式。
两个集合的初始内容不变,Person类的定义也不变。
*/
public class Demo02StreamTest {
public static void main(String[] args) {
//第一支队伍
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
one.add("老子");
one.add("庄子");
one.add("洪七公");
//1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。——过滤
//2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。——截取
Stream<String> oneStream = one.stream().filter(name -> name.length() == 3).limit(3);
//第二支队伍
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("尼古拉斯赵四");
two.add("张天爱");
two.add("张二狗");
//3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。——过滤
//4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。——跳过
Stream<String> twoStream = two.stream().filter(name -> name.startsWith("张")).skip(2);
//5. 将两个队伍合并为一个队伍;存储到一个新集合中。——合并
//6. 根据姓名创建Person对象;存储到一个新集合中。——映射(转换)
//7. 打印整个队伍的Person对象信息。——遍历(消费)
Stream.concat(oneStream, twoStream).map(name -> new Person(name)).forEach(p -> System.out.println(p));
}
}
运行结果
Person{name=‘宋远桥’}
Person{name=‘苏星河’}
Person{name=‘石破天’}
Person{name=‘张天爱’}
Person{name=‘张二狗’}