JAVA

1.1 接口的默认方法

1.1.1 为什么有默认方法

  • 解决接口的修改与现有的实现不兼容问题
  • 例如:Java8之前的集合框架添加foreach方法,需要在JDK里面相关的接口添加方法及实现。

1.1.2 什么是默认方法

  • 默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。
  • 通过default关键字向接口添加非抽象方法实现,此功能也称之为虚拟扩展方法。

1.1.3 如何使用默认方法

  • 语法
public interface Vehicle {
    default void print (){
        System.out.println("这是一个默认方法!");
    }
}
var foo = 'bar';
  • 实现多个接口,多个默认方法解决方案
    1、创建自己的默认方法,覆盖重写接口的默认方法
    2、使用super来调用指定接口的默认方法

1.2 Lambda表达式

1.2.1 为什么使用Lambda表达式

  • 开发快速,代码简洁,易于阅读
  • 减少匿名内部类的创建,节省资源
  • 易于“并发编程”;函数式编程不需要考虑“死锁”,因为它不修改变量,所以根本不存在“锁”线程的问题。

1.2.2 什么是Lambda表达式

Lambda允许把函数作为一个方法的参数(函数作为参数传递到方法中)

1.2.3 如何使用Lambda表达式

  • 语法
    (paraments)->expression或者(parameters)->{statements;}

1.2.4 Lambda应用场景

1.2.4.1 使用() -> {} 替代匿名类

Lamnda表达式要比匿名类简洁优雅很多

Thread t1=new Thread(new Runnable(){
    @Override
    public void run(){
        System.out.println("no use lambda");
    }
});
Thread t2=new Thread(()->System.out.println("use lambda"));

1.2.4.2 已流水线的方式处理数据

  • 借助stream api和Lambda表达式,以往需要定义多个变量,编写复杂的集合操作,现在都基本简化在一行之内完成。
//过滤初偶数列表
List<Integer> evens=intList.stream().filter(i->i%2==0).collect(Collections.toList());
//复合操作
List<Integer> list=intList.stream().filter(i->i%2==0).map(i->i*i).distinct.collection(Collections.toList());

1.2.4.3 更简单的数据并行处理

  • 数据并行处理,只需要在原来的基础上加一个parallel()就可以开启了。此方法开启的底层并行框架是fork/join,默认的并行数是Ncpu个
    List evens=intList.stream().parallel().filter(i->i%2==0).collect(Collections.toList());

1.2.4.4 内部迭代取代外部迭代

  • 外部迭代:描述怎么干,代码嵌套2个以上for循环,难读懂。
for(String f:flist){
   System.out.println(f);
}
  • 内部迭代:描述干什么;
flist.stream().forEach(n->System.out.println(n));

1.3 Lambda表达式作用域

1.3.1 访问局部变量(final)

  • 可访问标记了final的外层局部变量
  • 可访问隐形的具有final语义的外层变量
int num=1;
Converter<Integer,String>  str=(f)->String.volueOf(f+num);
str.convent(2);
//num=3;  表达式之后修改num不允许的

1.3.2 访问字段和静态变量

class Lambda4static int num;
    int n;
    void test{
        Converter<Integer,String> strCon1=(f)->{
            num=23;
            return String.valueOf(f);
        }
        Converter<Integer,String> strCon2=(f)->{
            n=2;            
            return String.valueOf(f);
        }
    }

1.4 函数式接口

1.4.1 为什么有函数式接口

  • 函数式接口作为Lambda表达式的目标类型
  • 单独为Lambda表达式新增函数类型,破坏既有的java类型,对类库造成严重影响

1.4.2 什么是函数式接口

  • Java8对对一类特殊类型的接口的称呼
  • 仅有一个抽象方法,可以有多个非抽象方法的接口

1.4.3 函数式接口的使用

1.4.3.1 常用的四大核心接口

函数式接口参数类型返回类型用途
Consumer消费型接口Tvoid对类型为T的对象应用操作。void accept(T t);
SupplierT返回类型为T的对象。T get();
public static void main(String args[]){
    List<Integer> list=Arrays.asList(1,2,3);
    eval(list,n->true);//输出所有元素
    eval(list,n->n%2==0);//输出所有的偶数
}
public static void eval(List<Integer> list,Predicate<Integer> pre){
    for(Integer n:list){
        if(pre.test(n)){
            System.out.println(n);
        }
     }
}

1.4.3.2 自定义函数接口使用

@FunctionalInterface
public interface Con<F,T>{
    T con(F f);
}
//将字符串转为整数类型
Con<String,Integer> c=(f)->Integer.valueOf(f);
Integer conInt=c.con("123");
System.out.println(conInt);

1.5 方法或构造函数的引用

1.5.1 为什么使用方法或构造函数的引用

  • 根据已有的方法实现来创造Lambda表达式,代码可读性更好

1.5.2 如何使用方法或构造函数的引用

@FunctionalInterface//Java8的接口
public interface Supplier<F,T>{
    T get();
}
class Car{
    public static void cre(final Supplier<Car> s){
        return s.get();
    }
    public static void col(final Car car){
        System.out.println(car.toString());
    }
    public void fol(final Car c){
        System.out.println(c.toString());
    }
    public void rep(){
        System.out.println(this.toString());
    }
}
  • 构造器引用
final Car  car=Car.cre(Car::new);
final  List<Car> cars=Arrays.asList(car);
  • 静态方法引用
cars.forEach(Car::col);
  • 特定类的任意对象的方法引用
cars.forEach(Car::rep);
  • 特定对象的方法引用
final Car pol=Car.cre(Car::new);
cars.forEach(pol:fol);

1.6 Optional类

1.6.1 为什么有Optional类

  • 去除代码中对null的检查(避免嵌套null检查)
  • 解决null引发的问题(NullPointerExpetion)

1.7 Stream

1.7.1 为什么使用Stream

  • 声明性—代码更加简洁、易懂
  • 可复合型—更灵活
  • 可并行—性能更好

1.7.2 什么是Stream

  • 一个来自数据源的元素序列并支持聚合操作
  • 数据源:流的来源。可以是集合、数组、I/O Channel、产生器generator等
  • 集合操作:流的数据处理功能支持类似数据库操作,例如filter、mao、reduce、find、match等
  • 流操作的两个重要特点
    流水线:很多流操作本身返回一个流,这样多个操作就可以链接起来,形成一个大的流水线。
  • 内部迭代:流提供内部迭代的方式,通过访问者模式实现。流库的内部迭代可以自动选择一种适合硬件的数据表示和并行实现。

1.7.3 Stream的使用

1.7.3.1 Stream的两大操作

  • 中间操作:可以链接起来的流操作。
  • 终端操作:关闭流的操作。

1.7.3.2 筛选(filter)与切片

  • filter(过滤/筛选):通过一个predicate接口来过滤并保留符合条件的元素
List<Integer> nums=Arrays.asList(1,2,3);
nums.stream().filter(i->i%2==0).forEach(System.out::println);
  • limit(截断流):返回一个不超过给定长度的流。
//返回热量超过300的头三道菜
List<Dish> diahs=menu.stream().filter(d->d.getCalories()>300).limit(3).collect(toList());
  • 跳过元素:返回一个扔掉前n元素的流。
//跳过超过300的头两道菜,返回剩余超过300的菜
List<Dish> diahs=menu.stream().filter(d->d.getCalories()>300).skip(2).collect(toList());

1.7.3.3 映射

  • map(映射):将元素根据指定的Fuction接口依次将元素转成另外的对象。
//提取流中菜肴的名称
List<Integer> dishNames=menu.stream().map(Dish::getName).collect(toList());
  • flatMap(流的扁平化):把一个流中的每个值都换成另外一个流,然后把所有的流链接成一个流。
//将words单词列表["Hellow","world"],返回每个字母去重后的列表["H","e","l","o","w","r","d"]
List<String> s=words.stream().map(w->w.split("")).flatMap(Arrays::stream).district().collect(toList());
//map(w->w.split(""))返回一个Stream<String[]>
//flatMap(Arrays::stream)将Stream<String[]>转变为Stream<String>

1.7.3.4 查找(find)与匹配(Match)

  • allMatch、anyMatch、noneMatch、findMatch、findAny
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_42242792

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值