第一章-lambda表达式
1.函数式编程思想和Lambda表达式定义格式
1.面向对象思想:
强调的是找对象,帮我们去做事儿
比如:去北京 -> 强调的是怎么去,火车,高铁,飞机,汽车,自行车,腿儿
2.jdk8开始有了一个新的思想:函数式编程思想:
强调的是结果,不强调过程
比如:去北京 -> 只强调去了还是没去
3.Lambda表达式语法:
a.定义格式:
()->{}
b.各部分解释:
() : 重写方法的参数位置
-> : 将参数传递到方法体中
{} : 重写方法的方法体位置
public class Demo01Lambda {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("我执行了");
}
}).start();
System.out.println("===================");
new Thread(()-> System.out.println("我执行了")).start();
}
}
2.Lambda表达式使用前提
1.必须是函数式接口做方法参数传递
2.啥叫做函数式接口
有且只有一个抽象方法的接口,用@FunctionalInterface去检测
3.Lambda表达式省略规则
1.Lambda表达式怎么写(涛哥给的新手教程)
a.观察是否是函数式接口做方法参数传递
b.如果是,考虑使用Lambda表达式
c.调用方法,以匿名内部类的形式传递实参
d.从new接口开始到重写方法的方法名结束,选中,删除,别忘记再删除一个右半个大括号
e.在重写方法的参数后面,方法体的大括号前面加上 ->
2.省略规则:
a.重写方法的参数类型可以干掉
b.如果重写方法只有一个参数,所在的小括号可以干掉
c.如果方法体中只有一句话,那么所在的大括号以及分号可以干掉
d.如果方法体中只有一句话并且带return,那么所在的大括号以及分号以及return可以干掉
public class Person {
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo02Lambda {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("张三",10));
list.add(new Person("李四",8));
list.add(new Person("王五",9));
/*Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});*/
Collections.sort(list, (Person o1, Person o2)-> {
return o1.getAge()-o2.getAge();
});
System.out.println("============Lambda表达式终极形式================");
Collections.sort(list, (o1,o2)-> o1.getAge()-o2.getAge());
System.out.println(list);
}
}
第二章-函数式接口
1.函数式接口:
有且只有一个抽象方法的接口
2.检测:
@FunctionalInterface
@FunctionalInterface
public interface USB {
void open(String s);
//void close();
}
public class Test01 {
public static void main(String[] args) {
method(new USB() {
@Override
public void open(String s) {
System.out.println(s+"开启了");
}
});
System.out.println("==========Lambda===========");
method((String s)-> {
System.out.println(s+"开启了");
});
System.out.println("========Lambda最终形式======");
method(s-> System.out.println(s+"开启了"));
}
public static void method(USB usb){
usb.open("鼠标");
}
}
1.Supplier
1.Supplier接口
java.util.function.Supplier<T>接口,它意味着"供给"->我们想要什么就给什么
2.方法:
T get() -> 我们想要什么,get方法就可以返回什么3.需求:
使用Supplier接口作为方法的参数
用Lambda表达式求出int数组中的最大值
4.泛型:
<引用数据类型>-> 规定了我们操作的数据是什么类型
<>中只能写引用数据类型,不能写基本数据类型
public class Demo01Supplier {
public static void main(String[] args) {
method(new Supplier<Integer>() {
@Override
public Integer get() {
int[] arr = {5,2,0,6,3,5,7};
Arrays.sort(arr);
return arr[arr.length-1];
}
});
System.out.println("========Lambda表达式======");
method(()-> {
int[] arr = {5,2,0,6,3,5,7};
Arrays.sort(arr);
return arr[arr.length-1];
});
}
public static void method(Supplier<Integer> supplier){
Integer max = supplier.get();//让get方法返回一个数组最大值
System.out.println("max = " + max);
}
}
2.Consumer
java.util.function.Consumer<T>->消费型接口->操作
方法:
void accept(T t),意为消费一个指定泛型的数据
"消费"就是"操作",至于怎么操作,就看重写accept方法之后,方法体怎么写了
public class Demo02Consumer {
public static void main(String[] args) {
method(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s.length());
}
},"abcdefg");
System.out.println("=====Lambda表达式=====");
method((String s)->{
System.out.println(s.length());
},"abcdefg");
System.out.println("========Lambda表达式终极写法=======");
method(s-> System.out.println(s.length()),"abcdefg");
}
public static void method(Consumer<String> consumer,String s){
consumer.accept(s);
}
}
3.Function
java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据
方法:
R apply(T t)根据类型T参数获取类型R的结果
public class Demo03Function {
public static void main(String[] args) {
method(new Function<Integer, String>() {
@Override
public String apply(Integer integer) {
return integer+"";
}
},100);
System.out.println("=======Lamba=======");
method(integer -> integer+"",200);
}
public static void method(Function<Integer,String> function,Integer number){
String result = function.apply(number);
System.out.println("result = " + result+1);
}
}
4.Predicate
java.util.function.Predicate<T>接口。->判断型接口
boolean test(T t)->用于判断的方法,返回值为boolean型
public class Demo04Predicate {
public static void main(String[] args) {
method(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() == 7;
}
}, "abcdefg");
System.out.println("==============");
method(s -> s.length()==7,"abcdefg");
}
public static void method(Predicate<String> predicate, String s) {
boolean result = predicate.test(s);
System.out.println("result = " + result);
}
}
第三章-Stream流
public class Demo01Stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张无忌");
list.add("张三丰");
list.add("张大彪");
list.add("吕不韦");
list.add("张三");
list.add("赵姬");
list.add("张翠山");
list.add("嫪毐");
//需求1:筛选出姓张的
/* ArrayList<String> listZhang = new ArrayList<>();
for (String s : list) {
if (s.startsWith("张")){
listZhang.add(s);
}
}
System.out.println(listZhang);
System.out.println("=====================");
*/
//需求2:筛选出三个字的
/* ArrayList<String> listThree = new ArrayList<>();
for (String s : listZhang) {
if (s.length()==3){
listThree.add(s);
}
}
System.out.println(listThree);*/
//需求3:遍历
/* for (String s : listThree) {
System.out.println(s);
}*/
System.out.println("===========================");
Stream<String> stream = list.stream();
stream.filter(s -> s.startsWith("张")).filter(s -> s.length()==3).forEach(s -> System.out.println(s));
}
}
1.Stream的获取
1.针对集合:Collection中的方法
Stream<E> stream();2.针对于数组:Stream接口中静态方法:
static <T> Stream<T> of(T... values)
public class Demo02Stream {
public static void main(String[] args) {
/*
针对集合:Collection中的方法
Stream<E> stream();
*/
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
Stream<String> stream = list.stream();
System.out.println(stream);
System.out.println("====================");
/*
针对于数组:Stream接口中静态方法:
static <T> Stream<T> of(T... values)
*/
Stream<String> stream2 = Stream.of("张三", "李四", "王五");
System.out.println("stream2 = " + stream2);
}
}
2.Stream的方法
2.1.Stream中的forEach方法:void forEach(Consumer<? super T> action);
forEach : 逐一处理->遍历
void forEach(Consumer<? super T> action);注意:forEach方法是一个终结方法,使用完之后,Stream流不能用了
public class Demo03Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六", "田七", "猪八");
/*stream.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
System.out.println("========Lambda表达式==========");
/* stream.forEach((String s)-> {
System.out.println(s);
});*/
System.out.println("========Lambda表达式终结写法==========");
stream.forEach(s-> System.out.println(s));
}
}
2.2.Stream中的long count()方法
1.作用:统计元素个数
2.注意:count也是一个终结方法
public class Demo04Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("飞天小女警", "马丁的早晨", "猫和老鼠", "封神榜传奇", "古希腊神话");
long count = stream.count();
System.out.println("count = " + count);
}
}
2.3.Stream中的Stream<T> filter(Predicate<? super T> predicate)方法
.方法:Stream<T> filter(Predicate<? super T> predicate)方法,返回一个新的Stream流对象
2.作用:根据某个条件进行元素过滤
public class Demo05Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("飞天小女警", "马丁的早晨", "猫和老鼠", "封神榜传奇", "古希腊神话");
/* Stream<String> stream1 = stream.filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() == 4;
}
});
stream1.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
/* stream.filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() == 4;
}
}).forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
System.out.println("========Lambda表达式======");
stream.filter(s-> s.length() == 4).forEach(s-> System.out.println(s));
}
}
2.4.Stream<T> limit(long maxSize):获取Stream流对象中的前n个元素,返回一个新的Stream流对象
1.Stream<T> limit(long maxSize):获取Stream流对象中的前n个元素,返回一个新的Stream流对象
public class Demo06Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("飞天小女警", "马丁的早晨", "猫和老鼠", "封神榜传奇", "古希腊神话");
stream.limit(3).forEach(s -> System.out.println(s));
}
}
2.5.Stream<T> skip(long n): 跳过Stream流对象中的前n个元素,返回一个新的Stream流对象
Stream<T> skip(long n): 跳过Stream流对象中的前n个元素,返回一个新的Stream流对象
public class Demo07Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("飞天小女警", "马丁的早晨", "猫和老鼠", "封神榜传奇", "古希腊神话");
stream.skip(2).forEach(s -> System.out.println(s));
}
}
2.6.static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b):两个流合成一个流
1.方法:static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b):两个流合成一个流
public class Demo08Stream {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("飞天小女警", "马丁的早晨", "猫和老鼠");
Stream<String> stream2 = Stream.of("西施", "貂蝉", "杨玉环","王昭君");
Stream.concat(stream1,stream2).forEach(s -> System.out.println(s));
}
}
2.7.将Stream流变成集合
从Stream流对象转成集合对象,使用Stream接口方法collect
public class Demo09Stream {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("飞天小女警", "马丁的早晨", "猫和老鼠");
List<String> list = stream1.collect(Collectors.toList());
for (String s : list) {
System.out.println(s);
}
}
}
2.8 Stream流练习
1. 第一个队伍只要名字为3个字的成员姓名;//filter
2. 第一个队伍筛选之后只要前3个人;//limit
3. 第二个队伍只要姓张的成员姓名;//filter
4. 第二个队伍筛选之后不要前2个人;//skip
5. 将两个队伍合并为一个队伍;//concat
6. 打印整个队伍的姓名信息。//foreach
public class Demo10Stream {
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("洪七公");
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
//将两个集合变成Stream流对象
Stream<String> oneTeam = one.stream();
Stream<String> twoTeam = two.stream();
//Stream<String> teamA = oneTeam.filter(s -> s.length() == 3).limit(3);
//Stream<String> teamB = twoTeam.filter(s -> s.startsWith("张")).skip(2);
Stream.concat(oneTeam.filter(s -> s.length() == 3).limit(3),twoTeam.filter(s -> s.startsWith("张")).skip(2)).forEach(s -> System.out.println(s));
}
}
第四章节-方法引用
1)方法引用的介绍
1.概述:引用方法
2.啥时候用:
a.被引用的方法要写在重写的方法里面
b.被引用的方法从参数上,返回值上要和所在重写方法一致,而且引用的方法最好操作重写方法的参数值
c.干掉重写方法的参数,干掉->,干掉被引用方法的参数,将.改成:
2)方法引用的体验
public class Demo01Method {
public static void main(String[] args) {
Stream<String> stream = Stream.of("曼曼", "三上", "金莲", "松下", "有菜", "井上");
/*
accept是重写方法: 参数类型为String
没有返回值
想引用println: println参数类型为String,被引用的方法操作重写方法的参数值
没有返回值
*/
/*stream.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
stream.forEach(System.out::println);
}
}
3)对象名--引用成员方法
1.使用对象名引用成员方法
格式:
对象::成员方法名
2.需求:
函数式接口:Supplier
java.util.function.Supplier<T>接口
抽象方法:
T get()。用来获取一个泛型参数指定类型的对象数据。
Supplier接口使用什么泛型,就可以使用get方法获取一个什么类型的数据
public class Demo02Method {
public static void main(String[] args) {
method(new Supplier<String>() {
/*
get为重写方法:无参的,返回值为String的
trim方法在get中:无参的,返回值为String的
考虑用方法引用
*/
@Override
public String get() {
return " abcd ".trim();
}
});
System.out.println("===================");
method(()-> " abcd ".trim());
System.out.println("=========方法引用==========");
method(" abcd "::trim);
System.out.println("===========================");
method(new Supplier<String>() {
/*
get():空参,返回值类型为String
toUpperCase:空参,返回值类型为String
*/
@Override
public String get() {
return "abcdefg".toUpperCase();
}
});
System.out.println("================");
method(()->"abcdefg".toUpperCase());
System.out.println("======方法引用=======");
method("abcdefg"::toUpperCase);
System.out.println("=======================");
method(()->"abcdefg".substring(1));
//method("abcdefg"::substring);
}
public static void method(Supplier<String> supplier){
String s = supplier.get();
System.out.println(s);
}
}
4)类名-引用静态方法
类名--引用静态方法
格式:
类名::静态成员方法
public class Demo03Method {
public static void main(String[] args) {
method(new Supplier<Double>() {
/*
get: 无参,返回值类型为Double
random:无参,返回值类型为double
*/
@Override
public Double get() {
return Math.random();
}
});
System.out.println("======Lambda表达式======");
method(()-> Math.random());
System.out.println("======方法引用======");
method(Math::random);
}
public static void method(Supplier<Double> supplier){
Double s = supplier.get();
System.out.println(s);
}
}
5)类-构造引用
1. 类--构造方法引用
格式:
构造方法名称::new
2.需求:
函数式接口:Function
java.util.function.Function<T,R>接口
抽象方法:
R apply(T t),根据类型T的参数获取类型R的结果。用于数类型转换
public class Demo04Constructor {
public static void main(String[] args) {
method(new Function<String, Person>() {
/*
apply:有一个String参数,返回值为Person类型
new Person(s): 一个参数的有参构造,参数为String,返回值类型为Person类型
Person p = new Person(s)
*/
@Override
public Person apply(String s) {
return new Person(s);
}
},"柳岩");
System.out.println("======Lambda======");
method(s -> new Person(s),"曼曼");
System.out.println("======方法引用=====");
method(Person::new,"曼曼");
}
public static void method(Function<String,Person> function,String name){
Person person = function.apply(name);
System.out.println(person);
}
}
6)数组引用
数组--数组引用
格式:
数组的数据类型[]::new
int[]::new 创建一个int型的数组
double[]::new 创建于一个double型的数组
public class Demo05Array {
public static void main(String[] args) {
method(new Function<Integer, int[]>() {
/*
apply:参数为Integer型,返回值类型为int[]
new int[integer]:[integer]看成参数,参数为Integer型
返回值类型为int[]
*/
@Override
public int[] apply(Integer integer) {
return new int[integer];
}
},10);
System.out.println("===========Lambda表达式=============");
method(integer-> new int[integer],10);
System.out.println("===========方法引用============");
method(int[]::new,10);
}
public static void method(Function<Integer,int[]> function,Integer len){
int[] arr = function.apply(len);
System.out.println(arr.length);
}
}