1. Experience Stream 【Understanding】
-
case requirements
Complete the creation and traversal of the collection according to the following requirements
-
Create a collection that stores multiple string elements
-
Store all elements starting with "Zhang" in the collection to a new collection
-
Store the elements of length 3 in the collection starting with "Zhang" into a new collection
-
Traverse the collection obtained in the previous step
-
-
Original way sample code
public class MyStream1 {
public static void main(String[] args) {
//集合的批量添加
ArrayList<String> list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));
//list.add()
//遍历list1把以张开头的元素添加到list2中。
ArrayList<String> list2 = new ArrayList<>();
for (String s : list1) {
if(s.startsWith("张")){
list2.add(s);
}
}
//遍历list2集合,把其中长度为3的元素,再添加到list3中。
ArrayList<String> list3 = new ArrayList<>();
for (String s : list2) {
if(s.length() == 3){
list3.add(s);
}
}
for (String s : list3) {
System.out.println(s);
}
}
}
- Use the Stream sample code
public class StreamDemo {
public static void main(String[] args) {
//集合的批量添加
ArrayList<String> list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));
//Stream流
list1.stream().filter(s->s.startsWith("张"))
.filter(s->s.length() == 3)
.forEach(s-> System.out.println(s));
}
}
-
Benefits of Streaming
-
Directly reading the literal meaning of the code can perfectly display the semantics of the irrelevant logic method: get stream, filter surname, filter length is 3, print one by one
-
Stream stream brings true functional programming style to Java
-
code concise
-
2. Common generation methods of Stream [Application]
-
The idea of Stream
-
Three types of methods of Stream
-
Get Stream stream
-
Create a pipeline and put data on the pipeline ready for operation
-
-
intermediate method
-
Operations on the pipeline
-
After one operation is completed, you can continue to perform other operations
-
-
Termination method
-
A Stream can only have one finalizer
-
is the last operation on the pipeline
-
-
-
The way to generate Stream stream
-
Collection system collection
Generate a stream using the default method stream(), default Stream<E> stream()
-
Map system collection
Convert the Map into a Set collection and generate streams indirectly
-
array
Generate a stream through the static method stream in Arrays
-
Multiple data of the same data type
Generate a stream through the static method of(T... values) of the Stream interface
-
-
code demo
public class StreamDemo {
public static void main(String[] args) {
//Collection体系的集合可以使用默认方法stream()生成流
List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<String>();
Stream<String> setStream = set.stream();
//Map体系的集合间接的生成流
Map<String,Integer> map = new HashMap<String, Integer>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();
//数组可以通过Arrays中的静态方法stream生成流
String[] strArray = {"hello","world","java"};
Stream<String> strArrayStream = Arrays.stream(strArray);
//同种数据类型的多个数据可以通过Stream接口的静态方法of(T... values)生成流
Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
Stream<Integer> intStream = Stream.of(10, 20, 30);
}
}
3. The intermediate operation method of Stream [Application]
-
concept
The intermediate operation means that after executing this method, the Stream stream can still continue to perform other operations
-
common method
method name illustrate Stream<T> filter(Predicate predicate) Used to filter the data in the stream Stream<T> limit(long maxSize) Returns a stream composed of elements in this stream, and intercepts the data of the specified number of parameters before Stream<T> skip(long n) Skips the data of the specified number of parameters and returns a stream consisting of the remaining elements of the stream static <T> Stream<T> concat(Stream a, Stream b) Merge two streams a and b into one stream Stream<T> distinct() Returns a stream consisting of the distinct elements of this stream (according to Object.equals(Object) )
filter code demo
public class MyStream3 { public static void main(String[] args) { // Stream<T> filter(Predicate predicate):过滤 // Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值 ArrayList<String> list = new ArrayList<>(); list.add("张三丰"); list.add("张无忌"); list.add("张翠山"); list.add("王二麻子"); list.add("张良"); list.add("谢广坤"); //filter方法获取流中的 每一个数据. //而test方法中的s,就依次表示流中的每一个数据. //我们只要在test方法中对s进行判断就可以了. //如果判断的结果为true,则当前的数据留下 //如果判断的结果为false,则当前数据就不要. // list.stream().filter( // new Predicate<String>() { // @Override // public boolean test(String s) { // boolean result = s.startsWith("张"); // return result; // } // } // ).forEach(s-> System.out.println(s)); //因为Predicate接口中只有一个抽象方法test //所以我们可以使用lambda表达式来简化 // list.stream().filter( // (String s)->{ // boolean result = s.startsWith("张"); // return result; // } // ).forEach(s-> System.out.println(s)); list.stream().filter(s ->s.startsWith("张")).forEach(s-> System.out.println(s)); } }
limit&skip code demo
public class StreamDemo02 { public static void main(String[] args) { //创建一个集合,存储多个字符串元素 ArrayList<String> list = new ArrayList<String>(); list.add("林青霞"); list.add("张曼玉"); list.add("王祖贤"); list.add("柳岩"); list.add("张敏"); list.add("张无忌"); //需求1:取前3个数据在控制台输出 list.stream().limit(3).forEach(s-> System.out.println(s)); System.out.println("--------"); //需求2:跳过3个元素,把剩下的元素在控制台输出 list.stream().skip(3).forEach(s-> System.out.println(s)); System.out.println("--------"); //需求3:跳过2个元素,把剩下的元素中前2个在控制台输出 list.stream().skip(2).limit(2).forEach(s-> System.out.println(s)); } }
concat&distinct code demo
public class StreamDemo03 { public static void main(String[] args) { //创建一个集合,存储多个字符串元素 ArrayList<String> list = new ArrayList<String>(); 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(s-> System.out.println(s)); //需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复 Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s)); } }
4. Operation method of Stream termination [Application]
-
concept
The final operation means that after executing this method, the Stream stream will no longer be able to perform other operations
-
common method
method name illustrate void forEach(Consumer action) perform an operation on each element of this stream long count() returns the number of elements in this stream -
code demo
public class MyStream5 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三丰");
list.add("张无忌");
list.add("张翠山");
list.add("王二麻子");
list.add("张良");
list.add("谢广坤");
//method1(list);
// long count():返回此流中的元素数
long count = list.stream().count();
System.out.println(count);
}
private static void method1(ArrayList<String> list) {
// void forEach(Consumer action):对此流的每个元素执行操作
// Consumer接口中的方法void accept(T t):对给定的参数执行此操作
//在forEach方法的底层,会循环获取到流中的每一个数据.
//并循环调用accept方法,并把每一个数据传递给accept方法
//s就依次表示了流中的每一个数据.
//所以,我们只要在accept方法中,写上处理的业务逻辑就可以了.
list.stream().forEach(
new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
}
);
System.out.println("====================");
//lambda表达式的简化格式
//是因为Consumer接口中,只有一个accept方法
list.stream().forEach(
(String s)->{
System.out.println(s);
}
);
System.out.println("====================");
//lambda表达式还是可以进一步简化的.
list.stream().forEach(s->System.out.println(s));
}
}
5. Stream collection operation 【Application】
-
concept
After using the Stream method to operate the data, you can collect the data in the stream into a collection
-
common method
method name illustrate R collect(Collector collector) Collect the results into a collection -
Tool class Collectors provide specific collection methods
method name illustrate public static <T> Collector toList() Collect the elements into the List collection public static <T> Collector toSet() Collect the elements into the Set collection public static Collector toMap(Function keyMapper,Function valueMapper) Collect the elements into the Map collection -
code demo
// toList和toSet方法演示
public class MyStream7 {
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list1.add(i);
}
list1.add(10);
list1.add(10);
list1.add(10);
list1.add(10);
list1.add(10);
//filter负责过滤数据的.
//collect负责收集数据.
//获取流中剩余的数据,但是他不负责创建容器,也不负责把数据添加到容器中.
//Collectors.toList() : 在底层会创建一个List集合.并把所有的数据添加到List集合中.
List<Integer> list = list1.stream().filter(number -> number % 2 == 0)
.collect(Collectors.toList());
System.out.println(list);
Set<Integer> set = list1.stream().filter(number -> number % 2 == 0)
.collect(Collectors.toSet());
System.out.println(set);
}
}
/**
Stream流的收集方法 toMap方法演示
创建一个ArrayList集合,并添加以下字符串。字符串中前面是姓名,后面是年龄
"zhangsan,23"
"lisi,24"
"wangwu,25"
保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
*/
public class MyStream8 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("zhangsan,23");
list.add("lisi,24");
list.add("wangwu,25");
Map<String, Integer> map = list.stream().filter(
s -> {
String[] split = s.split(",");
int age = Integer.parseInt(split[1]);
return age >= 24;
}
// collect方法只能获取到流中剩余的每一个数据.
//在底层不能创建容器,也不能把数据添加到容器当中
//Collectors.toMap 创建一个map集合并将数据添加到集合当中
// s 依次表示流中的每一个数据
//第一个lambda表达式就是如何获取到Map中的键
//第二个lambda表达式就是如何获取Map中的值
).collect(Collectors.toMap(
s -> s.split(",")[0],
s -> Integer.parseInt(s.split(",")[1]) ));
System.out.println(map);
}
}
6. Comprehensive exercise of Stream [Application]
-
case requirements
Now there are two ArrayList collections, which store the names of 6 actors and 6 actresses respectively, and the following operations are required
-
Actors only need the first three names with 3 characters
-
Actresses only need to be surnamed Lin, and don't need to be the first
-
Merge the filtered actor and actress names together
-
Use the elements after the previous step as the parameters of the constructor to create actor objects and traverse the data
The actor class Actor has been provided, which has a member variable, a construction method with parameters, and the get/set method corresponding to the member variable
-
-
Code
actor class
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;
}
}
test class
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> manStream = manList.stream().filter(s -> s.length() == 3).limit(3);
//女演员只要姓林的,并且不要第一个
Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);
//把过滤后的男演员姓名和女演员姓名合并到一起
Stream<String> stream = Stream.concat(manStream, womanStream);
// 将流中的数据封装成Actor对象之后打印
stream.forEach(name -> {
Actor actor = new Actor(name);
System.out.println(actor);
});
}
}