code学习

JAVA Stream流

体验Stream流

Stream流的好处:

直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印

Stream流把真正的函数式编程风格引入到Java中

1 /*案例需求
 2         按照下面的要求完成集合的创建和遍历
 3         创建一个集合,存储多个字符串元素
 4         把集合中所有以"张"开头的元素存储到一个新的集合
 5         把"张"开头的集合中的长度为3的元素存储到一个新的集合
 6         遍历上一步得到的集合*/
 7 
 8 import java.util.ArrayList;
 9 
10 public class StreamDemo {
11     public static void main(String[] args) {
12         //1.创建一个集合,存储多个字符串元素
13         ArrayList<String> arrayList=new ArrayList<>();
14 
15         arrayList.add("小龙女");
16         arrayList.add("张无忌");
17         arrayList.add("任盈盈");
18         arrayList.add("张三丰");
19         arrayList.add("张敏");
20         arrayList.add("令狐冲");
21 
22         //2.把集合中所有以"张"开头的元素存储到一个新的集合
23         ArrayList<String> zhangList=new ArrayList<>();
24         for (String s:arrayList) {
25             if (s.startsWith("张")) {
26                 zhangList.add(s);
27             }
28         }
29 
30         //3.把"张"开头的集合中的长度为3的元素存储到一个新的集合
31         ArrayList<String> threeList=new ArrayList<>();
32         for (String s:zhangList) {
33             if (s.length()==3) {
34                 threeList.add(s);
35             }
36         }
37 
38         //4.遍历上一步得到的集合
39         for (String s:threeList) {
40             System.out.println(s);
41         }
42 
43         System.out.println("--------");
44 
45         //Stream流改进
46         arrayList.stream().filter(s->s.startsWith("张")).filter(s -> s.length()==3).forEach(System.out::println);
47     }
48 }      

Stream流的常见生成方式

JAVA Stream流

Stream流的使用

  • 生成流

通过数据源(集合,数组等)生成流

list.stream()

  • 中间操作

一个流后面可以跟随零个或多个中间操作,其目的主要是打开流,做出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用

filter()

  • 终结操作

一个流只能有一个终结操作,当这个操作执行后,流就被使用"光"了,无法再被操作。所以这必定是流的最后一个操作

forEach()

生成Stream流的方式:

(1)Collection体系集合

使用默认方法stream()生成流, default Stream stream()

(2)Map体系集合

把Map转成Set集合,间接的生成流

(3)数组通过Stream接口的静态方法of(T… values)生成流

1 import java.util.*;
 2 import java.util.stream.Stream;
 3 
 4 public class StreamDemo {
 5     public static void main(String[] args) {
 6         //1.Collection体系的集合可以使用默认方法stream()生成流
 7         List<String> list=new ArrayList<>();
 8         Stream<String> listStream = list.stream();
 9 
10         Set<String> set=new HashSet<>();
11         Stream<String> setStream = set.stream();
12 
13         //2.Map体系的集合间接的生成流
14         Map<String,String> map=new HashMap<>();
15 
16         //Set<String> set1 = map.keySet();           可以看出键的集合是Set类型的
17         Stream<String> ketStream = map.keySet().stream();
18 
19         //Collection<String> values = map.values();    可以看出值的集合是Collection类型的
20         Stream<String> valueStream = map.values().stream();
21 
22         Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
23 
24         //3.数组可以通过Stream接口的静态方法of(T... values)生成流
25         String[] strArray = {"hello","world","java"};
26         Stream<String> array = Stream.of(strArray);
27 
28         //也可以:
29         Stream<String> stringStream = Stream.of("hello", "world", "java");
30         Stream<Integer> integerStream = Stream.of(10, 20, 30, 40);
31     }
32 }      

Stream流中间操作方法

概念:

中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作。

常见方法:

1 Stream filter(Predicate predicate) 用于对流中的数据进行过滤
 2 
 3 Stream limit(long maxSize) 返回此流中的元素组成的流,截取前指定参数个数的数据
 4 
 5 Stream skip(long n) 跳过指定参数个数的数据,返回由该流的剩余元素组成的流
 6 
 7 static Stream concat(Stream a, Stream b) 合并a和b两个流为一个流
 8 
 9 Stream distinct() 返回由该流的不同元素(根据Object.equals(Object) )组成的流
10 
11 Stream sorted() 返回由此流的元素组成的流,根据自然顺序排序
12 
13 Stream sorted(Comparator comparator)  返回由该流的元素组成的流,根据提供的Comparator进行排序
14 
15 Stream map(Function mapper)  返回由给定函数应用于此流的元素的结果组成的流
16 
17 IntStream mapToInt(ToIntFunction mapper)  返回一个IntStream其中包含将给定函数应用于此流的元素的结果      
1 (1)filter代码演示:
 2 
 3 import java.util.ArrayList;
 4 
 5 public class FilterDemo {
 6     public static void main(String[] args) {
 7         ArrayList<String> list=new ArrayList<>();
 8 
 9         list.add("林青霞");
10         list.add("张曼玉");
11         list.add("王祖贤");
12         list.add("柳岩");
13         list.add("张敏");
14         list.add("张无忌");
15 
16         //需求1:把list集合中以"张"开头的元素在控制台输出
17         list.stream().filter(s->s.startsWith("张")).forEach(System.out::println);
18         System.out.println("--------");
19         //需求2:把list集合中长度为3的元素在控制台输出
20         list.stream().filter(s->s.length()==3).forEach(System.out::println);
21         System.out.println("--------");
22         //需求3:把list集合中以张开头的,长度为3的元素在控制台输出
23         list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(System.out::println);
24     }
25 }      
1 (2)limit&skip代码演示:
 2 
 3 import java.util.ArrayList;
 4 
 5 public class StreamDemo02 {
 6     public static void main(String[] args) {
 7         ArrayList<String> list=new ArrayList<>();
 8 
 9         list.add("林青霞");
10         list.add("张曼玉");
11         list.add("王祖贤");
12         list.add("柳岩");
13         list.add("张敏");
14         list.add("张无忌");
15 
16         //需求1:取前3个数据在控制台输出
17         list.stream().limit(3).forEach(System.out::println);
18         System.out.println("--------");
19 
20         //需求2:跳过3个元素,把剩下的元素在控制台输出
21         list.stream().skip(3).forEach(System.out::println);
22         System.out.println("--------");
23 
24         //需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
25         list.stream().skip(2).limit(2).forEach(System.out::println);
26     }
27 }      
1 (3)concat&distinct代码演示:
 2 
 3 import java.util.ArrayList;
 4 import java.util.stream.Stream;
 5 
 6 public class StreamDemo03 {
 7     public static void main(String[] args) {
 8         ArrayList<String> list=new ArrayList<>();
 9 
10         list.add("林青霞");
11         list.add("张曼玉");
12         list.add("王祖贤");
13         list.add("柳岩");
14         list.add("张敏");
15         list.add("张无忌");
16 
17         //需求1:取前4个数据组成一个流
18         Stream<String> s1 = list.stream().limit(4);
19 
20         //需求2:跳过2个数据组成一个流
21         Stream<String> s2 = list.stream().skip(2);
22 
23         //需求3:合并需求1和需求2得到的流,并把结果在控制台输出
24         //Stream.concat(s1,s2).forEach(System.out::println);  //concat是静态方法,通过类名调用
25 
26         //需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
27         Stream.concat(s1,s2).distinct().forEach(System.out::println);
28     }
29 }      
1 (4)sorted代码演示:
 2 
 3 import java.util.ArrayList;
 4 
 5 public class StreamDemo04 {
 6     public static void main(String[] args) {
 7         ArrayList<String> list = new ArrayList<String>();
 8 
 9         list.add("linqingxia");
10         list.add("zhangmanyu");
11         list.add("wangzuxian");
12         list.add("liuyan");
13         list.add("zhangmin");
14         list.add("zhangwuji");
15 
16         //需求1:按照字母顺序把数据在控制台输出
17         list.stream().sorted().forEach(System.out::println);
18 
19         System.out.println("--------");
20 
21         //需求2:按照字符串长度把数据在控制台输出
22         list.stream().sorted((s1,s2)->{
23             int num=s1.length()-s2.length();
24             int num2= num==0?s1.compareTo(s2):num;
25             return num2;
26         }).forEach(System.out::println);
27     }
28 }      
1 (5)map&mapToInt代码演示:
 2 
 3 import java.util.ArrayList;
 4 
 5 public class StreamDemo05 {
 6     public static void main(String[] args) {
 7         ArrayList<String> list = new ArrayList<String>();
 8 
 9         list.add("10");
10         list.add("20");
11         list.add("30");
12         list.add("40");
13         list.add("50");
14         list.add("60");
15 
16         //需求:将集合中的字符串数据转换为整数之后在控制台输出
17         list.stream().map(s->Integer.parseInt(s)).forEach(System.out::println);
18         //list.stream().map(Integer::parseInt).forEach(System.out::println);
19 
20         list.stream().mapToInt(s->Integer.parseInt(s)).forEach(System.out::println);
21 
22         //int sum() 返回此流中元素的总和,mapToInt的特有方法
23         int result = list.stream().mapToInt(Integer::parseInt).sum();
24         System.out.println(result);
25     }
26 }      

Stream流终结操作方法

概念:

终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作。

常见方法:

1 void forEach(Consumer action)   对此流的每个元素执行操作      
1 long count()   返回此流中的元素数      
1 示例:
 2 import java.util.ArrayList;
 3 
 4 public class StreamDemo06 {
 5     public static void main(String[] args) {
 6         //创建一个集合,存储多个字符串元素
 7          ArrayList<String> list = new ArrayList<String>();
 8 
 9          list.add("林青霞");
10          list.add("张曼玉");
11          list.add("王祖贤");
12          list.add("柳岩");
13          list.add("张敏");
14          list.add("张无忌");
15 
16         //需求1:把集合中的元素在控制台输出
17         list.stream().forEach(System.out::println);
18         System.out.println("--------");
19 
20         //需求2:统计集合中有几个以张开头的元素,并把统计结果在控制台输出
21         long counts = list.stream().filter(s -> s.startsWith("张")).count();
22         System.out.println(counts);
23     }
24 }      

Stream流综合练习

案例需求

现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作

男演员只要名字为3个字的前三人

女演员只要姓林的,并且不要第一个

把过滤后的男演员姓名和女演员姓名合并到一起

把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据

演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法

1 演员类:
 2 public class Actors {
 3     private String name;
 4 
 5     public Actors() {
 6     }
 7 
 8     public Actors(String name) {
 9         this.name = name;
10     }
11 
12     public String getName() {
13         return name;
14     }
15 
16     public void setName(String name) {
17         this.name = name;
18     }
19 }      
1 import java.util.ArrayList;
 2 import java.util.stream.Stream;
 3 
 4 public class StreamTest {
 5     public static void main(String[] args) {
 6         //创建集合
 7         ArrayList<String> manList = new ArrayList<String>();
 8 
 9         manList.add("周润发");
10         manList.add("成龙");
11         manList.add("刘德华");
12         manList.add("吴京");
13         manList.add("周星驰");
14         manList.add("李连杰");
15 
16         ArrayList<String> womanList = new ArrayList<String>();
17 
18         womanList.add("林心如");
19         womanList.add("张曼玉");
20         womanList.add("林青霞");
21         womanList.add("柳岩");
22         womanList.add("林志玲");
23         womanList.add("王祖贤");
24         /*
25         //男演员只要名字为3个字的前三人
26         Stream<String> man = manList.stream().filter(s -> s.length() == 3).limit(3);
27 
28         //女演员只要姓林的,并且不要第一个
29         Stream<String> woman = womanList.stream().filter(s -> s.startsWith("林")).skip(1);
30 
31         //把过滤后的男演员姓名和女演员姓名合并到一起
32         Stream<String> stream = Stream.concat(man, woman);
33 
34         //把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
35         stream.map(Actors::new).forEach(p->System.out.println(p.getName()));
36         */
37         
38         //改进:
39         Stream.concat(manList.stream().filter(s -> s.length()==3),
40                         womanList.stream().filter(s -> s.startsWith("林")).skip(1)).
41                         map(Actors::new).forEach(p-> System.out.println(p.getName()));
42     }
43 }      

Stream流的收集操作

概念:

对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中。

常用方法:

1 R collect(Collector collector) 把结果收集到集合中      

工具类Collectors提供了具体的收集方式:

1 public static Collector toList() 把元素收集到List集合中
2 
3 public static Collector toSet() 把元素收集到Set集合中
4 
5 public static Collector toMap(Function keyMapper,Function valueMapper)  把元素收集到Map集合中      
1 示例:
 2 import java.util.*;
 3 import java.util.stream.Collector;
 4 import java.util.stream.Collectors;
 5 import java.util.stream.Stream;
 6 
 7 public class CollectDemo {
 8     public static void main(String[] args) {
 9         /*-------List
10         //创建List集合对象
11         List<String> list = new ArrayList<String>();
12 
13         list.add("林青霞");
14         list.add("张曼玉");
15         list.add("王祖贤");
16         list.add("柳岩");
17 
18         //需求1:得到名字为3个字的流
19         Stream<String> listStream = list.stream().filter(s -> s.length() == 3);
20 
21         //需求2:把使用Stream流操作完毕的数据收集到List集合中并遍历
22         List<String> names = listStream.collect(Collectors.toList());
23         for (String name:names) {
24             System.out.println(name);
25         }
26         */
27 
28 
29         /*-------Set
30         //创建Set集合对象
31         Set<Integer> set = new HashSet<Integer>();
32 
33         set.add(10);
34         set.add(20);
35         set.add(30);
36         set.add(33);
37         set.add(35);
38 
39         //需求3:得到年龄大于25的流
40         Stream<Integer> setStream = set.stream().filter(s -> s > 25);
41 
42         //需求4:把使用Stream流操作完毕的数据收集到Set集合中并遍历
43         Set<Integer> ages = setStream.collect(Collectors.toSet());
44         for (Integer age:ages) {
45             System.out.println(age);
46         }
47         */
48 
49         //-------Map
50         //定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组合而成
51         String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33", "柳岩,25"};
52 
53         //需求5:得到字符串中年龄数据大于28的流
54         Stream<String> arrayStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);
55 
56         //需求6:把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作键,年龄作值
57         Map<String, Integer> map = arrayStream.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
58 
59         Set<String> keySet = map.keySet();
60         for (String key:keySet) {
61             Integer value = map.get(key);
62             System.out.println(key+","+value);
63         }
64     }
65 }