一、概念理解
- 避免内部类定义过多,只留下核心代码
- 属于函数式变成的概念
- (params) -> expression[表达式]
- (params) -> statement[语句]
- (params) -> {statements}
a -> System.out.println("i like lambda-->"+a);
new Thread(()->System.out.println("多线程学习。。。")).start();
二、条件
- Functional Interface(函数式接口)
- 任何接口,如果只包含唯一一个抽象方法,那么他就是一个函数是借口。
- 可以通过lambda表达式创建该接口的对象
@FunctionalInterface//函数式接口注解,只能有一个抽象方法;
public interface Runnable{
public abstract void run();
}
JAVA8 中增加了一个新特性:default ,接口中非强制实现的方法;
三、跟着代码走
1. lambda 表达式的由来
/*
传统的方式
*/
public class Demo01 {
public static void main(String[] args) {
//3、创建类的实例,并调用方法
Like iLike = new ILike();
iLike.lambda();
}
}
//1、一个函数式接口
interface Like{
void lambda();
}
//2、实现类
class ILike implements Like{
@Override
public void lambda(){
System.out.println("i lile lambda");
}
}
/*
进化一:静态内部类
*/
public class Demo02 {
//2、实现类
static class ILike implements Demo02Like{
@Override
public void lambda(){
System.out.println("i lile lambda2");
}
}
public static void main(String[] args) {
//3、创建类的实例,并调用方法
Demo02Like iLike = new ILike();
iLike.lambda();
}
}
//1、一个函数式接口
interface Demo02Like{
void lambda();
}
/*
进化二:局部内部类
*/
public class Demo03 {
public static void main(String[] args) {
//2、实现类
class ILike implements Demo03Like{
@Override
public void lambda(){
System.out.println("i lile lambda3");
}
}
//3、创建类的实例,并调用方法
Demo03Like iLike = new ILike();
iLike.lambda();
}
}
//1、一个函数式接口
interface Demo03Like{
void lambda();
}
/*
进化三:匿名内部类
*/
public class Demo04 {
public static void main(String[] args) {
//2、创建匿名内部类
Demo04Like iLike = new Demo04Like(){
@Override
public void lambda() {
System.out.println("i like lambda4");
}
};
iLike.lambda();
}
}
//1、一个函数式接口
interface Demo04Like{
void lambda();
}
/*
进化四:lambda
*/
public class Demo05 {
public static void main(String[] args) {
Demo05Like iLike = ()->{
System.out.println("i like lambda5");
};
iLike.lambda();
}
}
//1、一个函数式接口
interface Demo05Like{
void lambda();
}
2. lambda 表达式的简化
/*
简化带一个参数的lambda
*/
public class Demo06 {
public static void main(String[] args) {
Demo06Like iLike = null;
iLike = (int a)->{
System.out.println("i like "+ a);
};
iLike.like(1);
//简化一(参数类型可以不写,JVM 编译器的“类型推断”)
iLike = (a)->{
System.out.println("i like "+ a);
};
iLike.like(2);
// 类型推断:
// String[] strs = {"aaa","bbb","ccc"}; 没问题
// String[] strs;
// strs = {"aaa","bbb","ccc"}; 有问题,推断不出来了;
//简化二
iLike = a->{
System.out.println("i like "+ a);
};
iLike.like(3);
//简化三
iLike = a->System.out.println("i like "+ a);
iLike.like(4);
}
}
interface Demo06Like{
void like(int a);
}
/*
简化带多个参数的lambda
*/
public class Demo07 {
public static void main(String[] args) {
Demo07Like iLike = null;
iLike = (int a,int b)->{
System.out.println("i like "+ a + "&"+b);
};
iLike.like(1,2);
//简化一
iLike = (a,b)->{
System.out.println("i like "+ a + "&"+b);
};
iLike.like(3,4);
//简化二
iLike = (a,b)->System.out.println("i like "+ a + "&"+b);
iLike.like(5,6);
}
}
interface Demo07Like{
void like(int a,int b);
}
3. 方法引用
3.1 普通方法引用
/*
方法引用:
1. 可以快速将一个 lambda 表达式的实现指向一个已经实现的方法;
2. 语法:方法的隶属者::方法名 (隶属者:静态方法--类、非静态方法--实例);
类::静态方法;
实例::非静态方法;
类::非静态方法;(这种有前提,两个参数,第一个参数是方法调用者,第二个参数是方法的参数);
例子:BiPredicate<String,String> bp = (x,y) -> s.equals(y);
BiPredicate<String,String> bp = String::equals;
注意:
1. 参数数量和类型 要与 接口中抽象方法的一致;
2. 返回值的类型 要与 接口中抽象方法的一致;
*/
public class Demo08 {
public static void main(String[] args) {
Demo07Like iLike = null;
Demo08Change demo08Change = (a,b)->sum(a,b);
int result = demo08Change.change(1,2);
System.out.println(result);
Demo08Change demo08Change1 = Demo08::sum;
int result1 = demo08Change1.change(3,2);
System.out.println(result1);
}
public static int sum(int a,int b){
return a + b;
}
}
@FunctionalInterface
interface Demo08Change{
int change(int a, int b);
}
3.2 构造方法引用
/*
方法引用--构造方法:
*/
public class Demo09 {
public static void main(String[] args) {
PersonFactory1 person1 = Person::new;
person1.getPerson();
PersonFactory2 person2 = Person::new;
person2.getPerson("张三",10);
}
}
@FunctionalInterface
interface PersonFactory1{
Person getPerson();
}
@FunctionalInterface
interface PersonFactory2{
Person getPerson(String name,Integer age);
}
class Person{
String name;
Integer age;
Person(){
System.out.println("Person 类的无参构造方法执行了");
}
Person(String name,Integer age){
this.name = name;
this.age = age;
System.out.println("Person 类的有参构造方法执行了");
}
}
3.3 数组引用
Function<Integer,String[]> fun = (x) -> new String[x];
String[] strs = fun.apply(10);
Function<Integer,String[]> fun1 = String[]::new;
String[] strs1 = fun1.apply(20);
四、综合案例
案例一:集合排序,ArrayList
public class Demo01 {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小红",1));
list.add(new Person("小明",4));
list.add(new Person("小王",3));
list.add(new Person("小李",6));
list.add(new Person("小张",2));
list.add(new Person("老王",7));
list.add(new Person("老李",4));
list.add(new Person("老张",7));
list.add(new Person("张总",9));
list.add(new Person("王副总",10));
// 方式1
list.sort(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o2.age - o1.age;
}
});
// 方式2
list.sort((o1,o2)->o2.age -o1.age);
// 方式3
Collections.sort(list,(o1,o2) -> o2.age - o1.age);
System.out.println(list);
}
static class Person{
String name;
Integer age;
Person(){
System.out.println("Person 类的无参构造方法执行了");
}
Person(String name,Integer age){
this.name = name;
this.age = age;
System.out.println("Person 类的有参构造方法执行了");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
}
// 案例二:集合排序,TreeSet
public class Demo02 {
public static void main(String[] args) {
TreeSet<Person> set = new TreeSet<>();
set.add(new Person("小红",1));
System.out.println(set);
}
}
这样写会报异常:
Exception in thread "main" java.lang.ClassCastException: Thread.lambda.excise.Person cannot be cast to java.lang.Comparable
改1:
public class Demo02 {
public static void main(String[] args) {
TreeSet<Person> set = new TreeSet<>((o1,o2) -> o2.age - o1.age);
set.add(new Person("小红",1));
set.add(new Person("小明",4));
set.add(new Person("小王",3));
set.add(new Person("小李",6));
set.add(new Person("小张",2));
set.add(new Person("老王",7));
set.add(new Person("老李",4));
set.add(new Person("老张",7));
System.out.println(set);
}
}
这样写,最后会把 age 重复的给去重,return 0 的去重
改2:
public class Demo02 {
public static void main(String[] args) {
TreeSet<Person> set = new TreeSet<>((o1,o2) -> {
if(o2.age >= o1.age){
return 1;
} else {
return -1;
}
});
set.add(new Person("小红",1));
set.add(new Person("小明",4));
set.add(new Person("小王",3));
set.add(new Person("小李",6));
set.add(new Person("小张",2));
set.add(new Person("老王",7));
set.add(new Person("老李",4));
set.add(new Person("老张",7));
System.out.println(set);
}
}
//案例三:集合遍历,ArrayList
public class Demo03 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list,5,8,7,4,9,6,1,2,0,3);
list.forEach(System.out::println);
System.out.println("==================================");
list.forEach(ele -> {
if(ele%2 ==0){
System.out.println(ele);
}
});
System.out.println("==================================");
list.forEach(new Util()::accept);
}
static class Util implements Consumer {
@Override
public void accept(Object o) {
System.out.println("XXX"+o);
}
}
}
/*
案例四:删除集合中的特定元素
*/
public class Demo04 {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小红",1));
list.add(new Person("小明",4));
list.add(new Person("小王",3));
list.add(new Person("小李",6));
list.add(new Person("小张",2));
list.add(new Person("老王",7));
list.add(new Person("老李",4));
list.add(new Person("老张",7));
//删除集合中 age > 5 的元素
list.removeIf(ele -> ele.age > 5);
list.forEach(System.out::println);
}
}
/*
案例五:创建线程
*/
public class Demo05 {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
});
thread.start();
}
}
五、系统内容的函数式接口
//Predicate<T> : 参数T 返回值boolean
// IntPredicate : int -> boolean
// LongPredicate : Long -> boolean
// DoublePredicate : Double -> boolean
//Consumer<T> : 参数T 返回值void
// IntConsumer : int -> void
// LongConsumer : Long -> void
// DoubleConsumer : Double -> void
//Function<T,R> : 参数T 返回值R
// IntFunction<R> : int -> R
// LongFunction<R> : Long -> R
// DoubleFunction<R> : Double -> R
// IntToLongFunction : int -> Long
// IntToDoubleFunction : int -> Double
// LongToIntFunction : Long -> int
// LongToDoubleFunction : Long -> Double
// DoubleToIntFunction : Double -> int
// DoubleToLongFunction : Double -> Long
//Supplier<T> : 参数无 返回值T
//UnaryOperator : 参数T 返回值T
//BinaryOperator<T> : 参数T,T 返回值T
//BiFunction<T,U,R> : 参数T,U 返回值R
//BiPredicate<T,U> : 参数T,U 返回值boolean
//BiConsumer<T,U> : 参数T,U 返回值void
//常用的:
//Predicate<T> Consumer<T> Function<T,R> Supplier<T>
//Predicate<T> : boolean test<T> : 断言型接口
//Consumer<T> : void accept<T> : 消费型接口
//Supplier<T> : void get<T> : 供给型接口
//Function<T,R> : R apply<T> : 函数型接口
六、闭包问题
public class Demo01 {
public static void main(String[] args) {
int a = getNumber().get();
System.out.println(a);
int b = 10;// jdk1.8 后 默认是 final 类型;(在局部内部类中,引用了同级别的局部变量时,该变量默认为 final)
Runnable r = () -> System.out.println("xxxx:"+b);
new Thread(r).start();
}
public static Supplier<Integer> getNumber(){
int num = 10;
return () -> {
return num;
};
}
}