- 视频+资料【链接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg 提取码:zjxs】
- Java基础--学习笔记(零起点打开java世界的大门)--博客汇总表
目 录
17_Stream流中间操作之concat&distinct
21_Stream流综合练习操作之forEach&count
01_函数式接口
1.1、函数式接口概述
函数式接口概念:有且仅有一个抽象方法的接口。
Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可以适用于Lambda使用的接口。
只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。如何检测一个接口是不是函数式接口:
- @FunctionalInterface
- 放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败。
注意事项:
- 我们自己定义函数式接口的时候,@FunctionalInterface是可选的,就算我不写这个注解,只要保证满足函数式接口定义的条件,也照样是函数式接口。但是,建议加上该注解。
报错:有多个抽象方法在这个接口中。
02_函数式接口作为方法的参数
1.2、函数式接口作为方法的参数
需求
- 定义一个类(RunnableDemo),在类中提供两个方法:
一个方法是:startThread(Runnable r) 方法参数Runnable是一个函数式接口。
一个方法是主方法,在主方法中调用startThread方法。
如果方法的参数是一个函数式接口,我们可以使用Lambda表达式作为参数传递。
- startThread(() -> System.out.printIn(Thread.currentThread().getName() + "线程启动了"));
03_函数式接口作为方法的返回值
1.3、函数式接口作为方法的返回值
需求描述
- 定义一个类(ComparatorDemo),在类中提供两个方法:
一个方法是:Comparator<String> getComparator() 方法返回值Comparator是一个函数式接口。
一个方法是主方法,在主方法中调用getComparator方法。
如果方法的返回值是一个函数式接口,我们可以使用Lambda表达式作为结果返回。
- private static Comparator<String> getComparator() {
return (s1, s2) -> s1.length() - s2.length();
}
比较器排序接口
04_常用函数式接口之Supplier
1.4、常用的函数式接口
Java8在java.util.function包下预定义了大量的函数式接口供我们使用。
我们重点来学习下面的4个接口:
- Supplier接口
- Consumer接口
- Predicate接口
- Function接口
1.5、Supplier接口
Supplier<T>:包含一个无参的方法。
- T get():获得结果。
- 该方法不需要参数,它会按照某种实现逻辑(由Lambda表达式实现)返回一个数据。
- Supplier<T>接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用。
常用方法:只有一个无参的方法。
05_Supplier接口练习之获取最大值
1.5、Supplier接口
Supplier<T>:包含一个无参的方法。
- T get():获得结果。
- 该方法不需要参数,它会按照某种实现逻辑(由Lambda表达式实现)返回一个数据。
- Supplier<T>接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用。
练习(案例需求)
- 定义一个类(SupplierTest),在类中提供两个方法:
一个方法是:int getMax(Supplier<Integer> sup) 用于返回一个int数组中的最大值
一个方法是主方法,在主方法中调用getMax方法
06_常用函数式接口之Consumer
1.6、Consumer接口
Consumer<T>:包含两个方法。
- void accept(T t):对给定的参数执行此操作。
- default Consumer<T> andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行 after操作。
- Consumer<T>接口也被称为消费型接口,它消费的数据的数据类型由泛型指定。
07_Consumer接口练习之按要求打印信息
1.6、Consumer接口
Consumer<T>:包含两个方法。
- void accept(T t):对给定的参数执行此操作。
- default Consumer<T> andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行 after操作。
- Consumer<T>接口也被称为消费型接口,它消费的数据的数据类型由泛型指定。
练习(案例需求)
- String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33"};
- 字符串数组中有多条信息,请按照格式:“姓名:XX,年龄:XX"的格式将信息打印出来。
- 要求:
把打印姓名的动作作为第一个Consumer接口的Lambda实例。
把打印年龄的动作作为第二个Consumer接口的Lambda实例。
将两个Consumer接口按照顺序组合到一起使用。
08_常用函数式接口之Predicate(1)
1.7、Predicate接口
Predicate<T>:常用的四个方法:
- boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值。
- default Predicate<T> negate():返回一个逻辑的否定,对应逻辑非。
- default Predicate<T> and(Predicate other):返回一个组合判断,对应短路与。
- default Predicate<T> or(Predicate other):返回一个组合判断,对应短路或。
- Predicate<T>接口通常用于判断参数是否满足指定的条件。
09_常用函数式接口之Predicate(2)
1.7、Predicate接口
Predicate<T>:常用的四个方法:
- boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值。
- default Predicate<T> negate():返回一个逻辑的否定,对应逻辑非。
- default Predicate<T> and(Predicate other):返回一个组合判断,对应短路与。
- default Predicate<T> or(Predicate other):返回一个组合判断,对应短路或。
- Predicate<T>接口通常用于判断参数是否满足指定的条件。
10_Predicate接口练习之筛选满足条件数据
1.7、Predicate接口
Predicate<T>:常用的四个方法:
- boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值。
- default Predicate<T> negate():返回一个逻辑的否定,对应逻辑非。
- default Predicate<T> and(Predicate other):返回一个组合判断,对应短路与。
- default Predicate<T> or(Predicate other):返回一个组合判断,对应短路或。
- Predicate<T>接口通常用于判断参数是否满足指定的条件。
练习描述
- String[] strArray = {"林青霞,30", "柳岩,34", "张曼玉,35", "貂蝉,31", "王祖贤,33"};
- 字符串数组中有多条信息,请通过Predicate接口的拼装 将符合要求的字符串筛选到集合ArrayList中,并遍历ArrayList集合。
- 同时满足如下要求:姓名长度大于2;年龄大于33。
- 分析
1.有两个判断条件,所以需要使用两个Predicate接口,对条件进行判断。
2.必须同时满足两个条件,所以可以使用and方法连接两个判断条件。
11_常用函数式接口之Function
1.8、Function接口
Function<T,R>:常用的两个方法:
- R apply(T t):将此函数应用于给定的参数。
- default <V> Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果。
- Function<T,R>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值。
12_Function接口练习之按照指定要求操作数据
1.8、Function接口
Function<T,R>:常用的两个方法:
- R apply(T t):将此函数应用于给定的参数。
- default <V> Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果。
- Function<T,R>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值。
练习描述
- String s = "林青霞,30";
- 请按照指定的要求进行操作:
- 将字符串截取得到数字年龄部分
- 将上一步的年龄字符串转换成为int类型的数据
- 将上一步的int数据加70,得到一个int结果,在控制台输出
- 请通过Function接口来实现函数拼接
13_体验Stream流
1.1、体验Stream流
案例需求:按照下面的要求完成集合的创建和遍历。
- 创建一个集合,存储多个字符串元素;
- 把集合中所有以"张"开头的元素存储到一个新的集合;
- 把"张"开头的集合中的长度为3的元素存储到一个新的集合;
- 遍历上一步得到的集合。
使用Stream流的方式完成过滤操作(Stream流的好处):
- list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
- 直接阅读代码的字面意思,即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印。
- Stream流把真正的函数式编程风格引入到Java中。
package com.itheima_01;
import java.util.ArrayList;
public class StreamDemo {
public static void main(String[] args) {
//1.创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//2.把集合中所有以"张"开头的元素存储到一个新的集合
ArrayList<String> zhangList = new ArrayList<String>();
for (String s : list) {
if (s.startsWith("张")) {
zhangList.add(s);
}
}
System.out.println(zhangList);
//3.把"张"开头的集合中的长度为3的元素存储到一个新的集合
ArrayList<String> threeList = new ArrayList<String>();
for (String s : zhangList) {
if (s.length() == 3) {
threeList.add(s);
}
}
System.out.println(threeList);
//4.遍历上一步得到的集合
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);
}
}
14_Stream流的常见生成方式
1.2、Stream流的常见生成方式
Stream流的思想
Stream流的使用
- 生成流
通过数据源(集合、数组等)生成流
list.stream()
- 中间操作
一个流后面可以跟随零个或多个中间操作,其目的主要是打开流,做出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用
filter()
- 终结操作
- 一个流只能有一个终结操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。
- forEach()
Stream流的常见生成方式
- Collection体系的集合可以使用默认方法stream()生成流
default Stream<E> stream()
- Map体系的集合间接的生成流
- 数组可以通过Stream接口的静态方法of(T... values)生成流
package com.itheima_02;
import java.util.*;
import java.util.stream.Stream;
public class StreamDemo {
public static void main(String[] args) {
//1.Collection体系的集合可以使用默认方法stream()生成流
List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<String>();
Stream<String> setStream = set.stream();
//2.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();
//3.数组可以通过Stream接口的静态方法of(T... values)生成流
String[] strArray = {"hello", "world", "java"};
Stream<String> strArrayStream1 = Stream.of(strArray);
Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
Stream<Integer> intStream = Stream.of(10, 20, 30);
}
}
15_Stream流中间操作之filter
1.3、Stream流的常见中间操作方法
概念:中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作。
- Stream<T> filter(Predicate predicate):用于对流中的数据进行过滤。
Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值。
16_Stream流中间操作之limit&skip
1.3、Stream流的常见中间操作方法
- Stream<T> filter(Predicate predicate):用于对流中的数据进行过滤。
Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值。
- Stream<T> limit(long maxSize):返回此流中的元素组成的流,截取前指定参数个数的数据。
- Stream<T> skip(long n):跳过指定参数个数的数据,返回由该流的剩余元素组成的流。
17_Stream流中间操作之concat&distinct
1.3、Stream流的常见中间操作方法
- Stream<T> filter(Predicate predicate):用于对流中的数据进行过滤。
Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值。
- Stream<T> limit(long maxSize):返回此流中的元素组成的流,截取前指定参数个数的数据。
- Stream<T> skip(long n):跳过指定参数个数的数据,返回由该流的剩余元素组成的流。
- static <T> Stream<T> concat(Stream a, Stream b):合并a和b两个流为一个流。
- Stream<T> distinct():返回由该流的不同元素(根据Object.equals(Object) )组成的流。
18_Stream流中间操作之sorted
1.3、Stream流的常见中间操作方法
- Stream<T> filter(Predicate predicate):用于对流中的数据进行过滤。
Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值。
- Stream<T> limit(long maxSize):返回此流中的元素组成的流,截取前指定参数个数的数据。
- Stream<T> skip(long n):跳过指定参数个数的数据,返回由该流的剩余元素组成的流。
- static <T> Stream<T> concat(Stream a, Stream b):合并a和b两个流为一个流。
- Stream<T> distinct():返回由该流的不同元素(根据Object.equals(Object) )组成的流。
- Stream<T> sorted():返回由此流的元素组成的流,根据自然顺序排序。
- Stream<T> sorted(Comparator comparator):返回由该流的元素组成的流,根据提供的Comparator进行排序。
Comparator接口中的方法 int compare(T o1, T o2)
19_Stream流中间操作之map&mapToInt
1.3、Stream流的常见中间操作方法
概念:中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作。
- Stream<T> filter(Predicate predicate):用于对流中的数据进行过滤。
Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值。
- Stream<T> limit(long maxSize):返回此流中的元素组成的流,截取前指定参数个数的数据。
- Stream<T> skip(long n):跳过指定参数个数的数据,返回由该流的剩余元素组成的流。
- static <T> Stream<T> concat(Stream a, Stream b):合并a和b两个流为一个流。
- Stream<T> distinct():返回由该流的不同元素(根据Object.equals(Object) )组成的流。
- Stream<T> sorted():返回由此流的元素组成的流,根据自然顺序排序。
- Stream<T> sorted(Comparator comparator):返回由该流的元素组成的流,根据提供的Comparator进行排序。
Comparator接口中的方法 int compare(T o1, T o2)
- <R> Stream<R> map(Function mapper):返回由给定函数应用于此流的元素的结果组成的流。
Function接口中的方法 R apply(T t)
- IntStream mapToInt(ToIntFunction mapper):返回一个IntStream其中包含将给定函数应用于此流的元素的结果。
IntStream:表示原始 int 流
ToIntFunction接口中的方法 int applyAsInt(T value)
20_Stream流终结
1.4、Stream流的常见终结操作方法
概念:终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作。
- void forEach(Consumer action):对此流的每个元素执行操作。
Consumer接口中的方法 void accept(T t):对给定的参数执行此操作
- long count():返回此流中的元素数。
21_Stream流综合练习操作之forEach&count
1.5、Stream流的练习
案例需求:现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作:
- 男演员只要名字为3个字的前三人;
- 女演员只要姓林的,并且不要第一个;
- 把过滤后的男演员姓名和女演员姓名合并到一起;
- 把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据。
演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法。
22_Stream流的收集操作
1.6、Stream流的收集操作
概念:对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中。
对数据使用Stream流的方式操作完毕后,我想把流中的数据收集到集合中,该怎么办呢?
Stream流的收集方法:
- R collect(Collector collector):把结果收集到集合中
- 但是这个收集方法的参数是一个Collector接口。
它是通过工具类Collectors提供了具体的收集方式:
- public static <T> Collector toList():把元素收集到List集合中
- public static <T> Collector toSet():把元素收集到Set集合中
- public static Collector toMap(Function keyMapper,Function valueMapper):把元素收集到Map集合中
package com.itheima_06;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CollectDemo {
public static void main(String[] args) {
//创建List集合对象
List<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
//需求1:得到名字为3个字的流
Stream<String> listStream = list.stream().filter(s -> s.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<Integer>();
set.add(10);
set.add(20);
set.add(30);
set.add(33);
set.add(35);
//需求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);
}
//定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组合而成
String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33", "柳岩,25"};
//需求5:得到字符串中年龄数据大于28的流
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 value = map.get(key);
System.out.println(key + "," + value);
}
}
}