不知道现在jdk的版本都到了13还是14了,到现在如果被问到jdk8的新特性都不知道的话还是说不过去的,这里简单的总结以下几点1.8的新特性,挑选几个好用的特性细说以下:
1、Lambda表达式的使用
2、方法引用
3、Stream流式操作
4、接口的变化
5、HashSet的变化
6、内存模型的变化
Demo连接:
优快云下载://download.youkuaiyun.com/download/weixin_45417573/12104150
一、Lambda表达式的使用
1、基本语法(1)
(参数1。。。参数n)->{执行的语句}
根据参数的多少,执行语句的多少也可以简写为
//一个参数,一个执行语句
参数->执行语句
//空参,一个执行语句
()->执行语句
2、适用场景
lambda适用场景必须是函数式接口,所谓函数式接口就是接口中只有一个抽象方法,这里可以使用@FunctionalInterface
修饰接口,当然,这个注解并不影响该接口是不是函数式接口,注解起到的作用只是一个判断的作用!类似于@Override
的作用
3、用法概述
(1)以runnable为例
package demo;
/**
* 测试
* @author wwy
* @date 2020年1月7日
* @version v0.0.1
*
*/
public class Test {
public static void main(String[] args) {
new Thread(
//jdk1.8之前,需要创建一个runnable的匿名内部类,重写run方法
new Runnable() {
@Override
public void run() {
System.out.println("jdk1.8之前,需要创建一个runnable的匿名内部类,重写run方法");
}
}).start();;
//jdk1.8之后,利用lambda,大大简化代码
new Thread(
()->System.out.println("jdk1.8之后,利用lambda,大大简化代码")
).start();
}
}
(2)自定义函数式接口的例子
package demo;
import java.util.ArrayList;
import java.util.List;
/**
* Lambda表达式的demo
* @author wwy
* @date 2020年1月7日
* @version v0.0.1
*
*/
public class LambdaTest {
/需求
//首先我们自定义了一个函数式接口
//接下来我们需要把这个接口的对象存放到ArrayList中
public static void main(String[] args) {
List<Lambda> list=new ArrayList<>();
///老方法实现
//1、定义匿名内部类,并重写抽象方法,返回一个接口对象
Lambda l=new Lambda() {
@Override
public void aa() {
System.out.println("aa");
}
};
//2、将接口对象放入ArrayList中
list.add(l);
新方法//
list.add(()->System.out.println("aa"));
}
}
/**
* 自定义函数式接口
* @author wwy
* @ClassName demo.LambdaTest.java
* @date 2020年1月15日 上午9:41:13
* @version v0.0.1
*
*/
@FunctionalInterface//此注解用于检测函数式接口
interface Lambda{
void aa();
}
总结:其实说简单点,lambda表达式就是用来代替匿名内部类使用的,当你需要使用匿名内部类而且这个匿名内部类有且只有一个抽象方法的时候就可以使用lambda表达式的格式来代替!
二、方法引用
(1)基本语法
#普通方法,静态方法
类名::方法
例:
package demo;
import java.util.Arrays;
import java.util.List;
/**
* 方法引用测试
* @author wwy
* @ClassName demo.MethodTest.java
* @date 2020年1月15日 上午9:51:02
* @version v0.0.1
*
*/
public class MethodTest {
public static void main(String[] args) {
//1、新建两个AA对象,放到ArrayList中
List<AA> list=Arrays.asList(new AA(),new AA());
//遍历list,并将所有的AA对象name修改成“一条狗”
list.forEach(AA::updateName);
//遍历list,并将所有的AA对象age修改成18
list.forEach(AA::aupdateAge);
//遍历集合,打印内容
list.forEach(System.out::println);
}
}
class AA{
private int age;
private String name;
@Override
public String toString() {
return "AA [age=" + age + ", name=" + name + "]";
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
//将对象的name改为一条狗
public void updateName() {
this.name="一条狗";
}
//根据传递的AA对象修改对象的age值
public static void aupdateAge(AA aa) {
aa.setAge(18);
}
}
三、流式操作
流式操作主要是方便我们遍历list和set集合,并在遍历时做一系列操作,其实就是一系列方法的组合!
我们一个List对象和一个set对象,在jdk1.8以后都可以调用一个stream()方法,返回一Stream对象,而这个Stream对象可以通过调用一系列方法结合lambda表达式进行操作
下面简单介绍几个方法:
(1)filter()过滤方法,参数传递一个lambda指定过滤规则
(2)map()映射方法
(3)forEach()遍历
…
具体就看例子吧:
package demo;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 流式操作demo
* @author wwy
* @ClassName demo.StreamTest.java
* @date 2020年1月15日 上午10:27:39
* @version v0.0.1
*
*/
public class StreamTest {
public static void main(String[] args) {
/遍历//
//新建一个List,存放BB对象
List<BB> list=Arrays.asList(new BB("张三",18,"男"),new BB("李四",19,"女"),new BB("王二",20,"女"),null,new BB("麻子",21,"男"));
//流失操作返回的Stream对象
Stream<BB> stream = list.stream();
//遍历打印
list.forEach(System.out::println);
System.out.println("========================");
//将list调用stream转换成流后进行过滤,去除空值,遍历
list.stream().filter(Objects::nonNull).forEach(System.out::println);
//将list调用stream转换成流后进行过滤,去除空值,并按照性别分组,返回一个map集合
System.out.println("========================");
Map<String, List<BB>> collect = list.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(BB::getSex));
//用流失操作遍历set集合
collect.keySet().stream().forEach(System.out::println);
//将list调用stream转换成流后进行过滤,去除空值,并筛选出年龄<=19的进行遍历
System.out.println("========================");
list.stream().filter(Objects::nonNull).filter(s->(s.getAge()<=19)).forEach(System.out::println);;
//将所有的姓名组成一个新的list集合
System.out.println("========================");
list.stream().filter(Objects::nonNull).map(BB::getName).collect(Collectors.toList()).forEach(System.out::println);
/判断/
//判断是否所有学生都大于18岁
System.out.println("========================");
boolean b = list.stream().filter(Objects::nonNull).allMatch(a->a.getAge()>=18);
System.out.println(b);
//找到第一个满足条件的对象
System.out.println("========================");
BB bb = list.stream().filter(Objects::nonNull).filter(a->a.getName().equals("张三")).findFirst().get();
System.out.println(bb);
}
}
/**
* 自定义BB类
* @author wwy
* @ClassName demo.StreamTest.java
* @date 2020年1月15日 上午10:28:33
* @version v0.0.1
*
*/
class BB {
private int age;
private String name;
private String sex;
public BB(String name,int age,String sex) {
super();
this.age = age;
this.name = name;
this.sex=sex;
}
public BB() {
super();
}
@Override
public String toString() {
return "BB [age=" + age + ", name=" + name + ", sex=" + sex + "]";
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
四、其他
1、接口的变化
接口的变化主要指的是jdk1.8以后接口中的方法可以拥有方法体(默认方法),这样一来就方便方法的实现类,可以只重写自己需要的方法
2、HashSet的变化
hashSet的变化主要是数据结构的变化,说白了就是红黑树的引入,大家都知道hashSet的数据结构是数组+链表,但是如果链表长度过大势必会增加性能开销,影响性能,那么在jdk1.8以后引入了红黑树,当链表长度到达8的时候转换为红黑树,当长度减小到6的时候变回链表结构
3、内存模型的变化
内存模型的变化其实主要是指的元数据区移至直接内存中