一、Lambda
组成Lambda三要素:形式参数、箭头、代码块
格式:(形式参数)->{代码块}
1.Lambda表达式练习(抽象方法无参无返回值)
public class HelloWorld {
public static void main(String[] args) throws IOException {
//在主方法中调用useEatable方法
Eatable e = new Eatablelmpl();
useEatable(e);
//匿名内部类
useEatable(new Eatablelmpl() {
@Override
public void eat() {
System.out.println("一天一苹果,医生远离我");
}
});
//Lambda表达式
useEatable(() -> {
System.out.println("一天一苹果,医生远离我");
});
}
private static void useEatable(Eatable e) {
e.eat();
}
}
public class Eatablelmpl implements Eatable{
@Override
public void eat() {
System.out.println("一天一苹果,医生远离我");
}
}
public interface Eatable {
void eat();
}
2.Lambda表达式练习(抽象方法带参无返回值)
//匿名内部类
useEatable(new Eatablelmpl() {
@Override
public void eat(String s) {
System.out.println(s);
System.out.println("医生远离我");
}
});
//Lambda表达式
useEatable((String s) -> {
System.out.println(s);
System.out.println("医生远离我");
});
3.Lambda表达式练习(抽象方法带参带返回值)
//匿名内部类
useEatable(new Eatablelmpl() {
@Override
public int add(int x,int y) {
return x+y;
}
});
//Lambda表达式
useEatable((int x,int y) -> {
return x+y;
});
4.Lambda表达式的省略模式
参数类型可以省略;
但是有多个参数的情况下,不能只省略一个;
如果参数只有一个,那么小括号可以省略;
如果代码块的语句只有一个,可以省略大括号和分号,如果有return,return也要省略
5.Lambda表达式和匿名内部类的区别
所需类型不同:
匿名内部类:可以是接口,可以是抽象类,可以是具体类
Lambda表达式:只能是接口
使用限制不同:
如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
实现原理不同:
匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码咋运行的时候动态生成
二、接口组成更新
1.接口组成更新概述
常量:public statin final
抽象方法:public abstract
默认方法:Java8
静态方法:Java8
私有方法:Java9
2.接口中的默认方法
格式:public default 返回值类型 方法名(参数列表){}
注意事项:默认方法不是抽象方法,所以不强制被重写,重写的时候去掉default关键字;public可以省略,default不能省略
public class HelloWorld {
public static void main(String[] args) throws IOException {
Eatable e=new Eatablelmpl();
e.shou1();
e.shou2();
e.shou3();
}
}
public interface Eatable {
void shou1();
void show2();
default void shou3(){
System.out.println("show3");
}
}
public class Eatablelmpl implements Eatable{
@Override
public void shou1() {
System.out.println("show1");
}
@Override
public void show2() {
System.out.println("show2");
}
}
3.接口中的静态方法
格式:public static 返回值类型 方法名(参数列表){}
注意事项:静态方法只能通过接口名调用,不能通过实现类名或者对象名调用;public可以省略,static不能省略
static void show4(){
System.out.println("show4");
}
Eatable.show4();
3.接口中的私有方法
格式1:public 返回值类型 方法名(参数列表){}
格式2:public static 返回值类型 方法名(参数列表){}
注意事项:默认方法可以调用私有的静态方法和非静态方法;静态方法只能调用私有的静态方法
public class HelloWorld {
public static void main(String[] args) throws IOException {
Eatable e=new EatableImpl();
e.show1();
e.show2();
Eatable.method1();
Eatable.method2();
}
}
public interface Eatable {
default void show1(){
System.out.println("show1方法开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
show();
System.out.println("show1方法执行结束");
}
default void show2(){
System.out.println("show2方法开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
show();
System.out.println("show2方法执行结束");
}
static void method1(){
System.out.println("method1方法开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
show();
System.out.println("method1方法执行结束");
}
static void method2(){
System.out.println("method2方法开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
show();
System.out.println("method2方法执行结束");
}
static void show(){
System.out.println("初级工程师");
System.out.println("中级工程师");
System.out.println("高级工程师");
}
}
4.方法引用:(::)
usePrintable(s -> System.out.println(s));
usePrintable(System.out::println);
方法引用符::该符号为引用运算符,而他所在的表达式被称为方法引用
Lambda表达式支持的方法引用
(1)引用类方法:类名::静态方法
public static void main(String[] args) {
useConverter((String s)->{
return Integer.parseInt(s);
});
useConverter(s -> Integer.parseInt(s));
useConverter(Integer::parseInt);
// Lambda表达式被类方法替代的时候,他的形式参数全部传递给静态方法作为参数
}
(2)引用对象的实例方法:对象::成员方法
public class HelloWorld {
public static void main(String[] args) {
usePrinter(s -> {
System.out.println(s.toUpperCase());
});
PrintString p=new PrintString();
usePrinter(p::printUpper);
// Lambda表达式被实例方法替代的时候,他的形式参数全部传递给静态方法作为参数
}
public static void usePrinter(Printer p){
p.printUpperCase("heeloworld");
}
}
public interface Printer {
void printUpperCase(String s);
}
public class PrintString {
public void printUpper(String s){
String result = s.toUpperCase();
System.out.println(result);
}
}
(3)引用类的实例方法:类名::成员方法
public static void main(String[] args) {
useMyString((String s, int x, int y) -> {
return s.substring(x,y);
});
useMyString((s,x,y)->s.substring(x,y));
useMyString(String::substring);
}
(3)引用构造器:类名::new
public class HelloWorld {
public static void main(String[] args) {
useStudentBuilder((String name,int age)->{
Student s=new Student(name,age);
return s;
});
useStudentBuilder(((name, age) -> new Student(name,age)));
useStudentBuilder(Student::new);
}
public static void useStudentBuilder(StudentBuilder s){
Student stu = s.build("谢老板", 32);
System.out.println(stu.getName()+stu.getAge());
}
}
三、函数式接口
1.概述
函数式接口:有且仅有一个抽象方法的接口
@Functionallnterface
放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败
2.函数式接口作为方法的参数
public class HelloWorld {
public static void main(String[] args) {
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动");
}
});
startThread(()-> System.out.println(Thread.currentThread().getName()+"线程启动"));
}
public static void startThread(Runnable r){
new Thread(r).start();
}
}
3.函数式接口作为方法的返回值
public class HelloWorld {
public static void main(String[] args) {
ArrayList<String> array=new ArrayList<>();
array.add("bbbb");
array.add("aa");
array.add("c");
array.add("ddd");
// Collections.sort(array);
// System.out.println(array);//[aa, bbbb, c, ddd]
Collections.sort(array,getComparator());
System.out.println(array);//[c, aa, ddd, bbbb]
}
public static Comparator<String> getComparator(){
// Comparator<String> comp=new Comparator<String>() {
// @Override
// public int compare(String s1, String s2) {
// return s1.length()-s2.length();
// }
// };
// return comp;
// return new Comparator<String>() {
// @Override
// public int compare(String s1, String s2) {
// return s1.length()-s2.length();
// }
// };
// return (String s1,String s2)->{
// return s1.length()-s2.length();
// };
return (s1,s2)->s1.length()-s2.length();
}
}
4.Supplier接口
public class HelloWorld {
public static void main(String[] args) {
String string = getString(() -> "林青霞");
System.out.println(string);
Integer integer = getInteger(() -> 30);
System.out.println(integer);
}
private static String getString(Supplier<String> sup){
return sup.get();
}
private static Integer getInteger(Supplier<Integer> sup){
return sup.get();
}
}
Supplier接口练习:获取最大值
public class HelloWorld {
public static void main(String[] args) {
int[] arr={19,50,28,37,46};
int maxValue=getMax(()->{
int max=arr[0];
for(int i=0;i<arr.length;i++){
if(arr[i]>max){
max=arr[i];
}
}
return max;
});
System.out.println(maxValue);
}
private static int getMax(Supplier<Integer> sup){
return sup.get();
}
}
5.Consumer接口
Comsumer<T>:包含两个方法
void accept(T t):对给定的参数执行此操作
default Consumer<T> andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作
Consumer<T>接口也被称为消费性接口,他消费的数据的数据类型由泛型指定
public class HelloWorld {
public static void main(String[] args) {
operatorString("林青霞",s -> System.out.println(s));
operatorString("林青霞",s -> System.out.println(s),s -> System.out.println(new StringBuilder(s).reverse().toString()));
}
public static void operatorString(String name, Consumer<String> con1){
con1.accept(name);
}
public static void operatorString(String name, Consumer<String> con1,Consumer<String> con2){
// con1.accept(name);
// con2.accept(name);
con1.andThen(con2).accept(name);
}
}
Consumer接口练习:按要求打印信息
public class HelloWorld {
public static void main(String[] args) {
String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33"};
operatorString(strArray, (String str) -> {
String name = str.split(",")[0];
System.out.print("姓名:" + name+",");
}, (String str) -> {
String age = str.split(",")[1];
System.out.println("年龄:" + age);
});
}
public static void operatorString(String[] strArray, Consumer<String> con1, Consumer<String> con2) {
for (String str : strArray) {
con1.andThen(con2).accept(str);
}
}
}
7.Predicated接口
public class HelloWorld {
public static void main(String[] args) {
// boolean b1 = checkString("hello", s -> s.length() > 8);
// System.out.println(b1);//false
boolean b2 = checkString("hello", s -> s.length() > 8);
System.out.println(b2);//true
boolean b3 = checkString("hello", s -> s.length() > 8, s -> s.length() < 15);
System.out.println(b3);//fasle//true
boolean b4 = checkString("helloworld", s -> s.length() > 8, s -> s.length() < 15);
System.out.println(b4);//true//true
}
public static boolean checkString(String s, Predicate<String> pre) {
// return pre.test(s);
return pre.negate().test(s);
}
// 同一个字符串给出两个不同的判断条件,最后把这两个判断的结果做逻辑与运算的结果作为最终的结果
public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2) {
// return pre1.and(pre2).test(s);
return pre1.or(pre2).test(s);
}
}
Predicated接口练习:筛选满足条件数据
public class HelloWorld {
public static void main(String[] args) {
String[] str = {"林青霞,30", "柳岩,34", "张曼玉,35", "貂蝉,31", "王祖贤,33"};
ArrayList<String> arrayList = checkString(str, s -> s.split(",")[0].length() > 2, s -> Integer.parseInt(s.split(",")[1]) > 33);
for (String s : arrayList) {
System.out.println(s);
}
}
public static ArrayList<String> checkString(String[] str, Predicate<String> pre1, Predicate<String> pre2) {
ArrayList<String> array = new ArrayList<>();
for (String s : str) {
if (pre1.and(pre2).test(s)) {
array.add(s);
}
}
return array;
}
}
8.Function接口
public class HelloWorld {
public static void main(String[] args) {
convert("100", s -> Integer.parseInt(s));//100
convert(100, i -> String.valueOf(i + 566));//666
convert("100", s -> Integer.parseInt(s), i -> String.valueOf(i + 566));//666
}
// 定义一个方法,把字符串转换int类型,在控制台输出
public static void convert(String s, Function<String, Integer> fun) {
int i = fun.apply(s);
System.out.println(i);
}
// 定义一个方法,把一个int类型的数据加上一个整数之后,转为字符串在控制台输出
public static void convert(Integer i, Function<Integer, String> fun) {
String s = fun.apply(i);
System.out.println(s);
}
// 定义一个方法,把一个字符串转换为int类型,把int类型的数据加上一个整数之后,转为字符串在控制台输出
public static void convert(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
// int i = fun1.apply(s);
// String str = fun2.apply(i);
// System.out.println(str);
String s1 = fun1.andThen(fun2).apply(s);
System.out.println(s1);
}
}
Function接口练习:按照指定要求操作数据
public class HelloWorld {
public static void main(String[] args) {
String s="林青霞,30";
convert(s,age->Integer.parseInt(age)+70);
}
public static void convert(String s, Function<String, Integer> fun) {
Integer age = fun.apply(s.split(",")[1]);
System.out.println(age);
}
}
四、Stream流
1.Stream流的常见生成方式
public class HelloWorld {
public static void main(String[] args) {
// Collection体系的集合可以使用默认方法Stream生成流
List<String> list = new ArrayList<>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<>();
Stream<String> setStream = set.stream();
// map体系的集合间接生成流
Map<String, Integer> map = new HashMap<>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();
// 数组可以通过Stream接口的静态方法of(T....values)生成流
String[] strArray = {"hello", "world", "java"};
Stream<String> strArray1 = Stream.of(strArray);
Stream<String> strArray2 = Stream.of("hello", "world", "java");
Stream<Integer> intStream = Stream.of(10, 20, 30);
}
}
2.Stream流的中间操作之filter
public class HelloWorld {
public static void main(String[] args) {
ArrayList<String > list=new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
// 把list集合中以张开头的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
// 把list集合中长度为3的元素在控制台输出
list.stream().filter(s -> s.length()==3).forEach(System.out::println);
// 把list集合中以张开头长度为3的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length()==3).forEach(System.out::println);
}
}
3.Stream流的中间操作之limit&&skip
public class HelloWorld {
public static void main(String[] args) {
ArrayList<String > list=new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
// 取前三个数据在控制台输出
list.stream().limit(3).forEach(System.out::println);//林青霞,张曼玉,王祖贤
// 跳过三个数据,剩下的数据在控制台输出
list.stream().skip(3).forEach(System.out::println);//柳岩,张敏,张无忌
// 跳过2个元素,把剩下元素的前两个在控制台输出
list.stream().skip(2).limit(2).forEach(System.out::println);//王祖贤,柳岩
}
}
3.Stream流的中间操作之concat&&distinct
public class HelloWorld {
public static void main(String[] args) {
ArrayList<String > list=new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
// 取前4个数据组成一个流
Stream<String> s1 = list.stream().limit(4);
// 跳过2个数据组成一个流
Stream<String> s2 =list.stream().skip(2);
// 合并以上两个流并在控制台输出
Stream.concat(s1,s2).forEach(System.out::println);
// 要求元素不能重复
Stream.concat(s1,s2).distinct().forEach(System.out::println);
}
}
4.Stream流的中间操作之sort
public class HelloWorld {
public static void main(String[] args) {
ArrayList<String > list=new ArrayList<>();
list.add("linqingxia");
list.add("zhangmanyu");
list.add("wangzuxian");
list.add("liuyan");
list.add("zhangmin");
list.add("zhangwuji");
// 按照字母顺序把数据在控制台输出
list.stream().sorted().forEach(System.out::println);
// 按照字符串长度把数据在控制台输出
list.stream().sorted((s1,s2)->{
int num=s1.length()-s2.length();
int num2=num==0?s1.compareTo(s2):num;
return num2;
}).forEach(System.out::println);
}
}
5.Stream流的中间操作之map&&mapToInt
public class HelloWorld {
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.add("60");
// 将集合中的字符串数据转换为整数之后在控制台输出 map:返回由给定函数应用于此流的元素的结果
list.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println);
list.stream().mapToInt(s -> Integer.parseInt(s)).forEach(System.out::println);
// int sum()返回此流中元素的总和
int sum = list.stream().mapToInt(s -> Integer.parseInt(s)).sum();
System.out.println(sum);
}
}
6.综合练习
public class HelloWorld {
public static void main(String[] args) {
ArrayList<String> manlist = new ArrayList<>();
manlist.add("周润发");
manlist.add("成龙");
manlist.add("刘德华");
manlist.add("吴京");
manlist.add("周星驰");
manlist.add("李连杰");
ArrayList<String> womanlist=new ArrayList<>();
womanlist.add("林心如");
womanlist.add("张曼玉");
womanlist.add("林青霞");
womanlist.add("柳岩");
womanlist.add("林志玲");
womanlist.add("王祖贤");
Stream<String> s1 = manlist.stream().filter(s -> s.length()==3).limit(3);
Stream<String> s2 = womanlist.stream().filter(s -> s.startsWith("林")).skip(1);
Stream<String> s3 = Stream.concat(s1, s2);
s3.map(Actor::new).forEach(p-> System.out.println(p.getName()));
}
}