java8新特性
1、接口中默认方法修饰为普通方法
2、lambda表达式
3、函数式接口
4、方法与构造函数引用
语法结构:
类名称::方法名称 (lambda表达式更加简洁的写法)
5、Stream流接口
6、Optonal类
接口中默认方法修饰为普通方法
在jdk8之前,interface之中可以定义变量和放法,变量必须使用public static final修饰,方法必须是使用public abstract修饰。
在jdk8之后,支持方法使用static、default修饰,并且可以写方法体,不需要子类重写。
lambda表达式
基础语法
():参数列表
->:分隔符
{}:方法体
总结:
(a,b) ->{
};
好处:简化我们匿名内部类的调用
/** * lambda表达式 */ public class OrderTest { public static void main(String[] args) { //使用匿名内部类调用orderService //写法1 OrderService orderService = new OrderService() { @Override public void get() { System.out.println("get"); } }; orderService.get(); //写法2 new OrderService() { @Override public void get() { System.out.println("get"); } }.get(); //写法3(lambda表达式) ((OrderService) () -> System.out.println("get")).get(); } } //声明当前接口为函数接口 @FunctionalInterface interface OrderService{ void get(); }
@Data class User{ private String name; private Integer age; public User(String name, Integer age) { this.name = name; this.age = age; } }
lambda表达式排序
ArrayList<User> userList = new ArrayList<>(); userList.add(new User("张三",25)); userList.add(new User("李四",15)); userList.add(new User("王五",35)); //排序规则,年龄小的排在前面 userList.sort((o1,o2) -> { return o1.getAge() - o2.getAge(); }); userList.forEach(u ->{ System.out.println(u.getName()); });
lambda表达式线程调用
class OrderTest3{ public static void main(String[] args) { new Thread(() ->{ System.out.println(Thread.currentThread().getName()); }); } }
lambda表达书必须依赖函数接口
函数接口的定义
1、接口中只能够允许一个抽象方法;
2、可以在接口中定义object类中的方法(重写);
3、可以使用default、static关键字修饰;
4、使用@FunctionalInterface表示该接口为函数式接口;
Stream流
Stream:非常精简的形式遍历集合实现过滤、排序等。通过stream流 + 内部类 + 实现指定方法 来达到指定功能(toSet、toMap、sorted等待);
Stream接口中相关方法示例:
实体类User
@Data class User{ private String name; private Integer age; public User(String name, Integer age) { this.name = name; this.age = age; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } User user = (User) o; return Objects.equals(name, user.name) && Objects.equals(age, user.age); } @Override public int hashCode() { return Objects.hash(name, age); } }
list转换成set集合
import lombok.Data; import java.util.ArrayList; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; public class Test { public static void main(String[] args) { ArrayList<User> userList = new ArrayList<>(); userList.add(new User("zs",18)); userList.add(new User("ls",7)); userList.add(new User("zs",18)); userList.add(new User("ww",28)); userList.add(new User("zs",18)); userList.add(new User("ww",28)); /** * 创建 stream()的两种方式 * 1、userList.stream();串行流(单线程) * 2、userList.parallelStream();并行流(多线程、效率更高) */ Stream<User> stream = userList.stream(); //转换成set集合 Set<User> userSet = stream.collect(Collectors.toSet()); //遍历 userSet.forEach(user -> { System.out.println(user); }); } }
list转map
/** * list转换成map */ public class Test02 { public static void main(String[] args) { ArrayList<User> userList = new ArrayList<>(); userList.add(new User("zs",18)); userList.add(new User("ls",7)); userList.add(new User("ww",28)); Stream<User> stream = userList.stream(); /** * list转换成map * toMap(k,v); * new Function<User, String>();() */ Map<String, User> userMap = stream.collect(Collectors.toMap(new Function<User, String>() { @Override public String apply(User user) { //使用user对象中的name作为key return user.getName(); } }, new Function<User, User>() { @Override public User apply(User user) { //使用user对象作为value return user; } })); userMap.forEach(new BiConsumer<String, User>() { @Override public void accept(String s, User user) { System.out.println(s + "," + user); } }); } }
lambda写法
Map<String, User> userMap = stream.collect(Collectors.toMap(user -> { //使用user对象中的name作为key return user.getName(); }, user -> { //使用user对象作为value return user; })); userMap.forEach((s, user) -> System.out.println(s + "," + user));
求和
public class Test03 { public static void main(String[] args) { Stream<Integer> integerStream = Stream.of(10, 5, 30); Optional<Integer> sum = integerStream.reduce(new BinaryOperator<Integer>() { @Override public Integer apply(Integer a, Integer b) { return a + b; } }); /** * lambda表达式写法 * Optional<Integer> sum = integerStream.reduce((a, b) -> a + b); */ System.out.println(sum); System.out.println(sum.get()); } }
排序
public class Test04 { public static void main(String[] args) { ArrayList<User> userList = new ArrayList<>(); userList.add(new User("zs",18)); userList.add(new User("ls",7)); userList.add(new User("ww",28)); Stream<User> stream = userList.stream(); Stream<User> sortedUserList = stream.sorted((o1, o2) -> { //年龄降序 return o2.getAge() - o1.getAge(); }); sortedUserList.forEach(user -> System.out.println(user)); } }
不一一举例...
方法引入
什么是方法引入?
1、结合lambda表达式是代码更加简洁
2、匿名内部类使用
3、方法引入
1、静态方法引入:类名::静态方法名称
2、对象方法引入:类名::实例方法名称
3、实例方法引入:new 对象,对象实例::方法引入
4、构造函数引入:类名::new
需要遵循一个规范:
方法引入的方法参数列表、返回类型与函数接口参数列表、返回类型必须保持一致;
/** * 方法引入 */ public class Test05 { public static void main(String[] args) { //1、普通匿名内部类的写法 MessageFace messageFace = new MessageFace() { @Override public String get(Integer a, Integer b) { return "匿名内部类写法:" + (a + b); } }; System.out.println(messageFace.get(1, 2)); //2、lambda表达式写法 MessageFace messageFace1 = (a, b) -> "lambda表达式写法:" + (a + b); System.out.println(messageFace1.get(1, 2)); //3、静态方法引入的写法(将当前静态方法staticGet引入) MessageFace messageFace2 = Test05::staticGet; System.out.println(messageFace2.get(1, 2)); //4、实例方法引入的写法(将当前实例方法objGet引入) MessageFace messageFace3 = new Test05()::objGet; System.out.println(messageFace3.get(1, 2)); //5、构造方法引入的写法(将User类中的无参构造方法引入) UserEntity userEntity = User::new; System.out.println("无参构造方法引入的写法:" + userEntity); //6、对象方法引入的写法(将User类中的参构造方法引入) UserPojo userPojo = Test05::pojoGet; System.out.println(userPojo.getUser(new Test05())); } public static String staticGet(Integer a,Integer b){ return "静态方法引入写法:" + (a + b); } public String objGet(Integer a,Integer b){ return "实例方法引入写法:" + (a + b); } public String pojoGet(){ return "对象方法引入写法"; } } //自定义函数接口 @FunctionalInterface interface MessageFace{ String get(Integer a, Integer b); } //自定义函数接口 @FunctionalInterface interface UserEntity{ User getUser(); } //自定义函数接口 @FunctionalInterface interface UserPojo{ String getUser(Test05 test05); }
Optional类
Optional类是一个可以为 null 的容器,如果值存在则 isPresent() 方法会返回 true,调用 get() 方法会返回该对象。
Optional可以保存类型 T 的值,或者 null,提供很多有用的方法,不用显式进行空值检测。
import com.ithailin.framework.java8.User; import java.util.Optional; import java.util.function.Predicate; /** * Optional类 * @author DHaiLin */ public class Test1 { private static User user; public static User getUser(){ return new User("test",18); } public static void main(String[] args) { //对当前user对象使用Opyional类进行空值检测,存在则直接获取 user 对象,不存在则调用 getUser() 方法获取 user 对象 user = Optional.ofNullable(user).orElseGet(() -> getUser()); System.out.println(user); } } /** * isPresent() */ class Test2{ public static void main(String[] args) { String st = null; Optional<String> st1 = Optional.ofNullable(st); //当前 st 若为 null,则会返回 false,若有值,则返回 true boolean present = st1.isPresent(); System.out.println(present); //当前 st 若有值,则返回 st 的值,若为 null,则返回 “test”(设置默认值) String test = Optional.ofNullable(st).orElse("test"); System.out.println(test); } } class Test3{ public static void main(String[] args) { String userName = null; //使用 filter过滤,自定义返回,当 user 为 ”test“时,返回 true,否则返回 false Optional<String> optional = Optional.ofNullable(userName).filter(new Predicate<String>() { @Override public boolean test(String s) { return "test".equals(s); } }); System.out.println(optional.isPresent()); } }