目录
1 JAVA8新特性
1.接口中默认方法修饰为普通方法
2.lambda表达式(重点)
3.函数接口
4.方法与构造函数引用 类名称:方法名称
5.Stream接口(重点)
1.2 接口定义方法
在JDK 1.8开始 支持使用static和default 修饰 可以写方法体,不需要子类重写。
方法:
普通方法 可以有方法体
抽象方法 没有方法体需要子类实现 重写。
public interface javaService {
//不需要再impl书写实现
void get();
}
1.3 Lambda表达式
LAMBADA 好处: 简化我们匿名内部类的调用。
Lambda+方法引入 代码变得更加精简。
public interface javaService {
//不需要再impl书写实现
void get();
}
public static void main(String[] args) {
//lambda表达式
((javaService) () -> System.out.println("获取get数据")).get();
//这个接口实现写在了下方
new javaService() {
@Override
public void get() {
System.out.println("获取get数据");
}
}.get();
}
1.3.1 Lambda表达式的规范
使用Lambda表达式 依赖于函数接口
- 在接口中只能够允许有一个抽象方法
- 在函数接口中定义object类中方法
- 使用默认或者静态方法
- @FunctionalInterface 表示该接口为函数接口
1.3.2 函数接口定义
- 在接口中只能有一个抽象方法
- @FunctionalInterface 标记为该接口为函数接口
- 可以通过default 修饰为普通方法
- 可以定义object类中的方法
1.3.3 Lambda的基础语法
() 参数列表
-> 分隔
{ } 方法体
(a,b)->{ }
快速写出lambda表达式(new Consumer)
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
}
});
Lambda表达式精简写法的进
public interface javaService {
//不需要再impl书写实现
String get(int i,int j);
}
public static void main(String[] args) {
//lambda表达式
javaService javaservice = (i,j)->{
return i+"==="+j;
};
System.out.println(javaservice.get(1,1));
}
进一步简化:
如果方法体中只有一条语句的情况下 可以不需要写{}
如果方法体只有一条return的情况下不需要些{}和return
String s = ((javaService)(i,j) -> i+"=="+j).get(1,2);
1.4 Lambda表达式遍历LIst
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
//正常遍历
// for (String s: list) {
// System.out.println(s);
// }
list.forEach(s -> {
System.out.println(s);
});
}
1.5 Stream流
*什么是stream流*
Stream 是JDK1.8 中处理集合的关键抽象概念,Lambda 和 Stream 是JDK1.8新增的函数式编程最有亮点的特性了,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL执行的数据库查询。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
Stream :非常方便精简的形式遍历集合实现 过滤、排序等。
1.6 List转Set集合
public static void main(String[] args) {
ArrayList<School> Schools = new ArrayList<>();
Schools.add(new School("eee","wwww"));
// Schools.add(new School("aaa","sss"));
// Schools.add(new School("aaa","sss"));
/**
* school的属性值都是相等的 但是new了两个对象 这两个对象的内存地址是不一样的 所以没去重
*/
School school = new School("aaa","sss");
Schools.add(school);
Schools.add(school);
/**
* 创建流有两种方式:
* 1.串行流stream() 单线程
* 2.并行流parallelStream() 多线程
* 并行流比串行流效率要高
*/
Set<School> set = Schools.stream().collect(Collectors.toSet());
System.out.println(set);
}
1.7 List转换map
public static void main(String[] args) {
ArrayList<School> Schools = new ArrayList<>();
Schools.add(new School("eee","wwww"));
Schools.add(new School("rrr","eee"));
Schools.add(new School("aaa","sss"));
Map<String, School> map = Schools.stream().collect(Collectors.toMap(new Function<School, String>() {
@Override
public String apply(School school) {
return school.getName();
}
}, new Function<School, School>() {
@Override
public School apply(School school) {
return school;
}
}));
map.forEach(new BiConsumer<String, School>() {
@Override
public void accept(String s, School school) {
System.out.println(s+"==="+school);
}
});
简化:
public static void main(String[] args) {
ArrayList<School> Schools = new ArrayList<>();
Schools.add(new School("eee","wwww"));
Schools.add(new School("rrr","eee"));
Schools.add(new School("aaa","sss"));
Map<String, School> map = Schools.stream().collect(Collectors.toMap(school -> school.getName(), school -> school));
map.forEach((s, school) -> System.out.println(s+"==="+school));
}
1.8 Stream将Reduce求和
Stream.of
用于为给定元素创建顺序流。我们可以传递单个元素或多个元素。
public static void main(String[] args) {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7);
Optional<Integer> reduce = integerStream.reduce((integer, integer2) -> integer + integer2);
System.out.println(reduce);
}
1.9 Stream的Max和Min
public static void main(String[] args) {
ArrayList<School> Schools = new ArrayList<>();
Schools.add(new School("eee",44));
Schools.add(new School("rrr",55));
Schools.add(new School("aaa",11));
Schools.stream().max((o1, o2) -> o1.getObjId()-o2.getObjId());
}
1.10 StreamMatch 匹配
anyMatch表示,判断的条件里,任意一个元素成功,返回true
allMatch表示,判断条件里的元素,所有的都是,返回true
noneMatch跟allMatch相反,判断条件里的元素,所有的都不是,返回true
public static void main(String[] args) {
ArrayList<School> Schools = new ArrayList<>();
Schools.add(new School("eee",44));
Schools.add(new School("rrr",55));
Schools.add(new School("aaa",11));
boolean b = Schools.stream().anyMatch(new Predicate<School>() {
@Override
public boolean test(School school) {
return "eee".equals(school.getName());
}
});
System.out.println(b);
}
1.11 StreamFor过滤器
public static void main(String[] args) {
ArrayList<School> Schools = new ArrayList<>();
Schools.add(new School("eee",44));
Schools.add(new School("rrr",55));
Schools.add(new School("aaa",11));
Schools.add(new School("aaa",20));
Schools.stream().filter(new Predicate<School>() {
@Override
public boolean test(School school) {
return "aaa".equals(school.getName()) && school.getObjId() >= 20;
}
}).forEach(new Consumer<School>() {
@Override
public void accept(School school) {
System.out.println(school);
}
});
}
1.12 Stream 的排序sorted(略)
1.13 Stream 的分页limit 和 skip
public static void main(String[] args) {
ArrayList<School> Schools = new ArrayList<>();
Schools.add(new School("eee",44));
Schools.add(new School("rrr",55));
Schools.add(new School("aaa",11));
Schools.add(new School("aaa",20));
//mysql limit(0,2) 这里skip(1)表示跳过一条,limit(2)取两条数据
Schools.stream().skip(1).limit(2).forEach(new Consumer<School>() {
@Override
public void accept(School school) {
System.out.println(school);
}
});
}
1.14 并行流和串行流的区别
串行流:单线程的方式操作; 数据量比较少的时候。
并行流:多线程方式操作;数据量比较大的时候,原理:
Fork join 将一个大的任务拆分n多个小的子任务并行执行,
最后在统计结果,有可能会非常消耗cpu的资源,确实可以
提高效率。
注意:数据量比较少的情况下,不要使用并行流。
2 方法引入
什么是方法引入
方法引入:需要结合lambda表达式能够让代码变得更加精简。
- 匿名内部类使用
- Lambda调用匿名内部类
- 方法引入
方法引入
- 静态方法引入: 类名::(静态)方法名称
- 对象方法引入 类名:: 实例方法名称
- 实例方法引入 new对象 对象实例::方法引入
- 构造函数引入 类名::new
需要遵循一个规范:
方法引入 方法参数列表、返回类型与函数接口参数列表与返回类型必须 要保持一致。
public interface javaService {
void get(int i);
}
public class Test {
public static void main(String[] args) {
//正常调用
// javaService javaService = (i) -> {
// Test.test11(i);
// };
// javaService.get(1);
//方法引用
javaService test11 = Test::test11;
test11.get(1);
}
private static void test11(int i){
System.out.println("方法");
}
}
2.1 方法引入之实例方法引入
方法引入 方法参数列表、返回类型与函数接口参数列表与返回类型必须 要保持一致。
public interface javaService {
String get();
}
public class Test {
public static void main(String[] args) {
//lambda表达式写法
// javaService java = ()-> "lambda表达式";
//方法引用的写法
javaService java = Test::objGet;
}
private static String objGet(){
return "引用方法之实例方法";
}
}
2.2 构造函数方法的引入
当返回类型是一个对象的时候,可以使用构造函数方法的引入
构造函数的引入:遵循的规范:函数接口返回值是对象,::new
public interface javaService {
School get();
}
public class Test {
public static void main(String[] args) {
//lambda表达式写法
// javaService java = ()->{
// return new School();
// };
//构造方法的引入(注意这里不是类了,而是实体类)
javaService java = School::new;
}
}
2.3 对象方法引入的使用方法
Test必须和这个类相同
public interface javaService {
String get(Test test);
}
public class Test {
public static void main(String[] args) {
javaService java = Test::objGet;
}
}
3 java8新特性Optional
3.1 Optional判断对象是否为空
public static void main(String[] args) {
String name = "111";
/**
* ofNullable 可以允许传递一个空值,会抛异常
* of 不可以传递一个空值,会报空指针异常
*/
Optional<String> name1 = Optional.ofNullable(name);
System.out.println(name1.get());
/**
* 如果name1为空返回false,不为空返回会true
*/
boolean present = name1.isPresent();
}
3.2 Optional过滤和判断默认值
默认值
public static void main(String[] args) {
String name = null;
Optional.ofNullable(name).orElse("如果为空默认值为");
}
过滤
public static void main(String[] args) {
String name = null;
Optional.ofNullable(name).filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return "qq".equals(s);
}
}).isPresent();
}
3.3 Optional实战代码优化案例
public static void main(String[] args) {
String name = null;
Optional.ofNullable(name).ifPresent(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println("不为空");
}
});
//简化
Optional.ofNullable(name).ifPresent(s -> System.out.println("不为空"));
//可以调用构造方法引用
Optional.ofNullable(name).ifPresent(System.out::print);
}
3.4 orElseGet与orElse
public class Test {
private static School school;
public static void main(String[] args) {
System.out.println(Test.getSchool());
}
public static School getSchool(){
// if (school == null){
// school = createSchool();
// }
// return school;
/**
* orElseGet-----写函数接口的形式赋值默认值 全局
* orElse------直接传默认值 方法中
*/
return Optional.ofNullable(school).orElseGet(new Supplier<School>() {
@Override
public School get() {
school = createSchool();
return school;
}
});
}
private static School createSchool(){
return new School("1111",111);
}
}
继续简化,修改成方法引入的形式
public class Test {
private static School school;
public static void main(String[] args) {
System.out.println(Test.getSchool());
}
public static School getSchool(){
// if (school == null){
// school = createSchool();
// }
// return school;
/**
* orElseGet-----写函数接口的形式赋值默认值 全局
* orElse------直接传默认值 方法中
*/
return Optional.ofNullable(school).orElseGet(Test::orElseGet);
}
private static School createSchool(){
return new School("1111",111);
}
//修改成方法引入
private static School orElseGet(){
school = createSchool();
return school;
}
}
public static String getSchool(){
//优化前的写法
// School school = new School("aaa", 111);
// if (school!=null){
// String name = school.getName();
// if (name!=null){
// return name.toLowerCase();
// }
// }
// return null;
//优化后的写法
return Optional.ofNullable(school).map(School -> School.getName()).map(name -> name.toLowerCase()).orElseGet(null);
}