jdk8新特性
接口中生命的默认方法为普通方法
接口中不仅可以定义静态方法、抽象方法,还可以使用default关键字来定义普通方法也叫默认方法(可以有方法实现)
Lambda表达式
为什么使用lambda表达式
为了能够更精简的使用匿名内部类,实例:
package tengfei.lambdaTest;
public interface OrderService {
void get();
}
package tengfei.lambdaTest;
public class MainTest {
public static void main(String[] args) {
/*
* 我们知道接口是不能通过new创建实例对象的
* 1、使用接口的实现类(子类)
* 2、使用匿名内部类
* */
OrderService orderService = new OrderService() {
@Override
public void get() {
System.out.println("--_--");
}
};
orderService.get();
new OrderService() {
@Override
public void get() {
System.out.println("匿名内部类,相当于OrderService接口的实现类,也就是子类");
}
}.get();
//上面两种写法一样
}
}
函数式接口
函数式接口特性:
- 使用@FunctionalInterface注解修饰
- 接口中只定义一个抽象方法,但是可以定义多个默认方法(default)
- 可以重写Object类中的方法
package tengfei.functionalInterfaceTest;
@FunctionalInterface
public interface MyFunctionalInterface {
void add();
default void get(){
System.out.println("可以定义默认方法");
}
//可以重写Object中的方法
String toString();
}
lambda基础语法
() -> {}
参数列表 -> 方法实现体
精简写法
package tengfei.functionalInterfaceTest;
public class MainTest {
public static void main(String[] args) {
/*
* lambda简化写法(无参)
* 第一步、第二步、第三步
* */
MyFunctionalInterface myFunctionalInterface = ()->{
System.out.println("精简第一步");
};
myFunctionalInterface.add();
//当方法体只有一条语句时
MyFunctionalInterface myFunctionalInterface1 = ()-> System.out.println("精简第二步");
myFunctionalInterface1.add();
((MyFunctionalInterface)()-> System.out.println("精简第三步")).add();
/*
* lambda简化语法(有参)
* */
//第一步
MyFunctionalInterfaceReturn myFunctionalInterfaceReturn = (i,j)->{return i+"--"+j;};
myFunctionalInterfaceReturn.get(1,2);
//第二步
MyFunctionalInterfaceReturn myFunctionalInterfaceReturn1 = (i, j) -> i+"--"+j;
myFunctionalInterfaceReturn1.get(1,2);
//第三步
((MyFunctionalInterfaceReturn)(i,j)->i+"--"+j).get(1,2);
}
}
使用lambda操作集合
以下三个案例,均是在开发过程中出现lambda表达式用法的常见场景,这里目的是理解lambda的写法
遍历集合
package tengfei.operateListByLambda;
import java.util.ArrayList;
public class MainTest {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("ma");
arrayList.add("teng");
arrayList.add("fei");
arrayList.forEach(str->{
System.out.println(str);
});
arrayList.forEach(s -> System.out.println(s));
}
}
集合排序
package tengfei.operateListByLambda;
import tengfei.entity.User;
import java.util.ArrayList;
import java.util.Comparator;
public class MainTest01 {
public static void main(String[] args) {
ArrayList<User> users = new ArrayList<>();
users.add(new User("小虎",12));
users.add(new User("小狗",8));
users.add(new User("小王",24));
users.sort(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
users.sort(((o1, o2) -> o1.getAge().compareTo(o2.getAge())));
users.forEach((user -> System.out.println(user.toString())));
}
}
线程调用
package tengfei.operateListByLambda;
public class MainTest02 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}).start();
//精简
new Thread(()-> System.out.println(Thread.currentThread().getName())).start();
}
}
Stream流
为什么要使用Stream流
- stream流能够简洁的实现集合的遍历、过滤、排序等
- 分类:串行流
stream()
、并行流parallelStream()
Stream流将list集合转为set集合
package tengfei.Stream;
import tengfei.entity.User;
import java.util.ArrayList;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
ArrayList<User> users = new ArrayList<>();
users.add(new User("李华",18));
users.add(new User("小明",21));
users.add(new User("张三",24));
users.add(new User("张三",24));
Stream<User> stream = users.stream();
Set<User> set = stream.collect(Collectors.toSet());
set.forEach(user -> System.out.println(user.toString()));
}
}
//执行结果
User{name='张三', age=24}
User{name='小明', age=21}
User{name='李华', age=18}
User{name='张三', age=24}
产生疑问:
- 为什么list转为set集合,集合中的数据没有去重?
- Set集合底层去重的原理–》双等号和equals的区别
答:因为这里定义的User实体类没有重写equals方法,此时User实体类对象仍然使用的是Object类中的equals方法,查看源码可知,Object类中的equals方法里面使用的也是双等号,而对应引用对象User,两个具有相同的属性值通过new关键字创建的两个对象地址值不同当然equlas返回的就是true
Stream流将list集合转为map集合
package tengfei.Stream;
import tengfei.entity.User;
import java.util.ArrayList;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamTest01 {
public static void main(String[] args) {
ArrayList<User> users = new ArrayList<>();
users.add(new User("李华",18));
users.add(new User("小明",21));
users.add(new User("张三",24));
/*
* 单列集合只有元素,也就是双列集合的value
* 转为双列集合前提要指定key
* */
Stream<User> stream = users.stream();
//Collectors.toMap(key,value)
Map<String, User> map = stream.collect(Collectors.toMap(new Function<User, String>() {
@Override
public String apply(User user) {
return user.getName();
}
}, new Function<User, User>() {
@Override
public User apply(User user) {
return user;
}
}));
//简化写法
Map<String, User> userMap = stream.collect(Collectors.toMap(user -> user.getName(), user -> user));
}
}
Stream流计算求和
package tengfei.Stream;
import tengfei.entity.User;
import java.util.ArrayList;
import java.util.Optional;
import java.util.function.BinaryOperator;
import java.util.stream.Stream;
public class StreamTest02 {
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(10, 10, 20, 10);
Optional<Integer> sum = stream.reduce(new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) {
return integer + integer2;
}
});
System.out.println(sum.get());
//计算下面三人的年龄之和
ArrayList<User> users = new ArrayList<>();
users.add(new User("李华",18));
users.add(new User("小明",21));
users.add(new User("张三",24));
Stream<User> stream1 = users.stream();
Optional<User> ageSum = stream1.reduce(new BinaryOperator<User>() {
@Override
public User apply(User user, User user2) {
return new User("年龄之和", user.getAge() + user2.getAge());
}
});
System.out.println(ageSum.get());
}
}
Stream查找最大值和最小值
package tengfei.Stream;
import tengfei.entity.User;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Stream;
public class StreamTest03 {
public static void main(String[] args) {
ArrayList<User> users = new ArrayList<>();
users.add(new User("李华",18));
users.add(new User("小明",21));
users.add(new User("张三",24));
Stream<User> stream = users.stream();
Optional<User> max = stream.max(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getAge() - o2.getAge();
}
});
System.out.println(max.get());
}
}
Stream的Match用法
package tengfei.Stream;
import tengfei.entity.User;
import java.util.ArrayList;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class MainTest04 {
public static void main(String[] args) {
ArrayList<User> users = new ArrayList<>();
users.add(new User("李华",18));
users.add(new User("小明",21));
users.add(new User("张三",24));
Stream<User> stream = users.stream();
boolean b = stream.anyMatch(new Predicate<User>() {
@Override
public boolean test(User user) {
return user.getAge() > 18;
}
});
System.out.println(b);
}
}
Stream的过滤器用法
package tengfei.Stream;
import tengfei.entity.User;
import java.util.ArrayList;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class StreamTest05 {
public static void main(String[] args) {
ArrayList<User> users = new ArrayList<>();
users.add(new User("李华",18));
users.add(new User("李华",24));
users.add(new User("小明",21));
users.add(new User("张三",24));
Stream<User> stream = users.stream();
stream.filter(new Predicate<User>() {
@Override
public boolean test(User user) {
return "李华".equals(user.getName())&&user.getAge()>18;
}
}).forEach(user -> System.out.println(user.toString()));
}
}
Stream实现分页limit
package tengfei.Stream;
import tengfei.entity.User;
import java.util.ArrayList;
import java.util.stream.Stream;
public class StreamTest06 {
public static void main(String[] args) {
ArrayList<User> users = new ArrayList<>();
users.add(new User("李华",18));
users.add(new User("李华",24));
users.add(new User("小明",21));
users.add(new User("张三",24));
Stream<User> stream = users.stream();
stream.skip(1).limit(2).forEach(user -> System.out.println(user.toString()));
}
}
Stream实现排序
package tengfei.Stream;
import tengfei.entity.User;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.stream.Stream;
public class StreamTest07 {
public static void main(String[] args) {
ArrayList<User> users = new ArrayList<>();
users.add(new User("李华",18));
users.add(new User("李华",24));
users.add(new User("小明",21));
users.add(new User("张三",24));
Stream<User> stream = users.stream();
stream.sorted(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getAge()-o2.getAge();
}
}).forEach(user -> System.out.println(user.toString()));
}
}
综合案例
package tengfei.Stream;
import tengfei.entity.User;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class StreamTest08 {
public static void main(String[] args) {
ArrayList<User> users = new ArrayList<>();
users.add(new User("李华一",18));
users.add(new User("李华",24));
users.add(new User("李华明",34));
users.add(new User("小明",21));
users.add(new User("张三",24));
/*
* 年龄降序,名称包含“李华”,获取前两位
* */
Stream<User> stream = users.stream();
stream.filter(new Predicate<User>() {
@Override
public boolean test(User user) {
return user.getName().contains("李华");
}
}).sorted(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return -(o1.getAge()-o2.getAge());
}
}).limit(2).forEach(user -> System.out.println(user.toString()));
//简写
stream.filter(user -> user.getName().contains("李华"))
.sorted((o1, o2) -> o2.getAge()-o1.getAge())
.limit(2)
.forEach(user -> System.out.println(user.toString()));
}
}
方法引入
什么是方法引入
需要结合lambda表达式能够使代码更加简洁,lambda表达式的作用是为了匿名内部类更加简洁
规范:
- 能够使用方法引入的前提:被引入的方法它的参数列表 和 方法返回值类型 要与函数式接口定义的方法参数列表和方法返回值类型一致
方法引入之静态方法
类名::静态方法名
package tengfei.方法引入;
@FunctionalInterface
public interface MyTest {
void get(int a);
}
package tengfei.方法引入;
public class StaticTest {
public static void main(String[] args) {
MyTest test = new MyTest() {
@Override
public void get(int a) {
System.out.println("匿名内部类"+a);
}
};
test.get(1);
MyTest test1 = (a) -> System.out.println("lambda表达式"+a);
test1.get(1);
MyTest test2 = (a)-> StaticTest.staticGet(a);
test2.get(1);
//方法引入
MyTest test3 = StaticTest::staticGet;
test3.get(1);
}
//定义一个静态方法
public static void staticGet(Integer a){
System.out.println("这是一个静态方法"+a);
}
}
方法引入之实例方法引入
new 实例对象
对象实例::实例方法
package tengfei.方法引入;
public class Test02 {
public static void main(String[] args) {
Test02 obj = new Test02();
MyTest test = (a) -> obj.testGet(a);
MyTest test1 = obj::testGet;
test1.get(1);
}
//定义一个类实例方法
public void testGet(Integer a){
System.out.println("这是一个实例方法!"+a);
}
}
方法引入之构造函数引入
package tengfei.方法引入;
import tengfei.entity.User;
public class Test03 {
public static void main(String[] args) {
MyTest test = (a)-> new User();
test.get(1);
MyTest test1 = User::new;
test1.get(1);
}
}
方法引入之对象方法引入
package tengfei.方法引入;
@FunctionalInterface
public interface MyDefaultInterface {
void get(Test04 test04);
}
package tengfei.方法引入;
public class Test04 {
public static void main(String[] args) {
MyDefaultInterface myDefaultInterface = new MyDefaultInterface() {
@Override
public void get(Test04 test04) {
test04.defaultMethod();
}
};
myDefaultInterface.get(new Test04());
//lambda表达式
MyDefaultInterface myDefaultInterface1 = Test04::defaultMethod;
myDefaultInterface1.get(new Test04());
}
//定义一个普通方法
public void defaultMethod(){
System.out.println("这是一个类的实例方法");
}
}
Optional
Optional类是一个可以为null的容器对象。如果值存在则 isPresent()方法会返回true,调用get(方法会返回该对象;
Optional是个容器,它可以保存类型T的值,或者仅仅保存null;
Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
判断对象是否为空
package tengfei.optionalTest;
import java.util.Optional;
public class Test01 {
public static void main(String[] args) {
String username = null;
//ofNullable(arg),该方法参数可以为空
Optional<String> optional = Optional.ofNullable(username);
//username为空返回值false,不为空返回为true
boolean present = optional.isPresent();
System.out.println(optional.get());
}
}
过滤和设置默认值
package tengfei.optionalTest;
import java.util.Optional;
import java.util.function.Predicate;
public class Test02 {
public static void main(String[] args) {
String username = null;
//设置默认值
// String s = Optional.ofNullable(username).orElse("default");
// System.out.println(s);
//过滤
boolean present = Optional.ofNullable(username).filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return "default".equals(s);
}
}).isPresent();
System.out.println(present);
}
}
代码优化
package tengfei.optionalTest;
import java.util.Optional;
import java.util.function.Consumer;
public class Test03 {
public static void main(String[] args) {
String username = null;
Optional<String> optional = Optional.ofNullable(username);
boolean b = optional.isPresent();
if (b){
System.out.println("username不为空再进行具体的操作");
}
//优化
Optional<String> optional1 = Optional.ofNullable(username);
optional1.ifPresent(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println("如果username不为空,就执行这个方法");
}
});
//简化
optional1.ifPresent(s -> System.out.println(s));
optional1.ifPresent(System.out::println);
}
}