JDK1.8 接口的新特性
接口中 默认方法可以覆盖 静态方法不可以覆盖
在JDK1.8中对接口的一些改动。
-
函数式接口的注解@FunctionalInterface
函数式接口的概念:只有一个抽象方法的接口,其中抽象接口的接口名不能和Object中的方法重名。
若重名则这个接口不能算是函数式接口。
-
接口内的default 方法和static 方法
总结
1)接口中的abstract抽象方法通过实例对象来调用;
2)接口中的default方法通过实例对象来调用;
3)接口中的静态方法通过接口名.方法名()的方式来调用;
4)接口是不允许直接使用new的方式来获取实例的,如果new可以使用匿名实现类的方式:new后面跟上一对花括号来实现接口中的抽象方法。(匿名实现类:顾名思义没有名称的实现类,优点是不用再单独声明一个类;缺点是没有名字,不能重复使用,只能使用一次。)
其中@FunctionalInterface注解表示:
通过JDK8源码javadoc,可以知道这个注解有以下特点:
1、该注解只能标记在"有且仅有一个抽象方法"的接口上。
2、JDK8接口中的[静态方法和默认方法](http://blog.youkuaiyun.com/aitangyong/article/details/54134385),都不算是抽象方法。
3、接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。
4、该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。
lambda
在之前我们使用接口的方法的时候需要使用接口的实现类
当接口只使用一次 我们就不必创建实现类来使用接口方法
可以使用匿名内部类
//接口 A
@FunctionalInterface
interface A {
void ser(int a,int b);
}
匿名内部类的使用方式
A a = new A() {
@Override
public void ser() {
System.out.println(11111);
}
};
a.ser();
使用lambda
1.无参数
//JDK1.8的新特性 lambda
A a1 = ()-> System.out.println(123);
//就可以直接来使用接口的实现方法
a1.ser();
2.有参数
//当接口方法需要参数的时候
//直接在括号里面写入类型 和参数名就可以
A a2 = (int a,int b)-> System.out.println("a:"+a+",b:"+b);
a2.ser(10,20);
3.当方法里面需要写入多行代码时
//当我们需要在实现方法里面写多行代码的时候怎么办呢?
//可以使用{} 把代码写入里面 就可以了
A a3 = (int a,int b)->{
System.out.println(a);
System.out.println(b);
};
a3.ser(1,2);
4.当方法有返回值的时候
//方式一
A a4 = (int a,int b)->a+b;
int ser = a4.ser(10, 20);
System.out.println(ser);
//方式二
A a4 = (int a,int b)->{
return a+b
};
int ser = a4.ser(10, 20);
System.out.println(ser);
5.遍历集合
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
//第一种 jdk1.8新特性之前的写法
for (Integer integer : list) {
System.out.println(integer);
}
System.out.println("==========================");
//第二种 使用lambda表达式
Consumer<Integer> action = (t)-> System.out.println(t);
list.forEach(action);
System.out.println("==========================");
//还可以这样写 在方法里面把lambda写入
list.forEach(t-> System.out.println(t));
System.out.println("===========================");
//第三种 使用方法引入
list.forEach(System.out::println);
使用lambda实现接口
1.consumer接口
参数列表 T 返回值类型 void
Consumer<String> consumer = (String s)->{
String[] split = s.split(",");
for (String s1 : split) {
System.out.println(s1);
}
};
consumer.accept("10,20,30,40,50");
2.Predicate接口
参数列表 T 返回值类型 boolean
//实现Predicate
Predicate<String> predicate = (String string)->{
/*
* endsWith是用来判断里面的字符串是否是最后一个
* 比如lanqiao o是否是最后一个 是就返回ture 反之返回false
* 长字符串同理 lanqiao 放入 qiao 也返回true 但放入 qia 就会返回false
* contains方法可以判断输入的字符串是否存在比对的字符串里面
* */
if(string.endsWith("qia")){
return true;
}else {
return false;
}
};
System.out.println(predicate.test("lanqiao"));
3.Function接口
参数列表 T 返回值类型 R
Function<String,Integer> function = (string)-> Integer.parseInt(string);
System.out.println(function.apply("123"));
4.Supplier接口
参数列表 void 返回值类型 T
Supplier<User> supplier = ()-> new User();
System.out.println(supplier.get().toString());
案例
public static void main(String[] args) {
List<Integer> integers = Arrays.asList(10, 20, 30, 40, 50, 60,70,80);
/*
* 方法wapperList的两个参数
* 参数一:List类型 代表成绩的集合
* 参数二:Function接口类型,
* 我们就可以通过重写function来对集合中的成绩进行任意的操作
* */
List<Integer> integerList = wapperList(integers, (integer) -> {
//在这里我们就重写了function 让每个成绩都加了5
return integer + 5;
});
//遍历
for (Integer integer : integerList) {
System.out.println(integer);
}
}
//这个方法的作用就是把集合成绩抽出来
public static<R,T> List<T> wapperList(List<T> list, Function<T,R> function){
//使用新的数组来存储
LinkedList<T> linkedList = new LinkedList<>();
for (T l : list) {
/*
* 在添加成绩的时候使用了function被重写以后里面的方法
* 在这里通过重写Function接口来对每一个人的成绩进行修改
* */
linkedList.add((T) function.apply(l));
}
return linkedList;
}
*方法引入
1.静态方法引用 类名::静态方法
2.对象方法引用 对象名::成员方法
3.类构造器引用 类名::new
4.数组构造器引用 类型名[]::new
*只要是返回值 和参数列表相同 就可以使用
//例如 Consumer类
void accept(T var1);
List<Integer> integers = Arrays.asList(10, 20, 30, 40, 50);
Consumer<Integer> consumer = (Integer num)-> System.out.println(num);
//println的方法参数和返回值和consumer的参数和返回值相同 我们就可以直接使用println方法来替代
integers.forEach(System.out::println);
1.静态方法引用
static class B{
public static int abs(int num){
return Math.abs(num);
}
}
public static void main(String[] args) {
A a1 = B::abs;
System.out.println(a1.abs(-10));
}
2.对象方法引用
interface A{
int abs(int number);
}
public static void main(String[] args) {
//只要是返回值 和参数列表相同 就可以使用
A a = Math::abs;//等同于 A a = num-> Math.abs(num)
int abs = a.abs(-12);
System.out.println(abs);
}
list.forEach(System.out::println);//System.out其实是一个对象,就是调用了println这个方法来打印
//他的效果和 下面这个一样
list.forEach(t-> System.out.println(t));
Optional
简介
从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)
本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。
Optional 是 Java 实现函数式编程的强劲一步,并且帮助在范式中实现。但是 Optional 的意义显然不止于此。
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
方法
empty
//源码
private static final Optional<?> EMPTY = new Optional();
public static <T> Optional<T> empty() {
Optional<T> t = EMPTY;
return t;
}
一般是用于创建Optional对象
Optional<Object> optional = Optional.empty();//emppty--》 new Optional();
System.out.println(optional);//Optional.empty
of
//源码
public static <T> Optional<T> of(T value) {
return new Optional(value);
}
存入Value值到Optional
Optional<String> optional = Optional.of(null);
//获取到的值:Optional[123]
如果存入的值是 null 就会抛出异常
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4XSaC8W5-1619322479432)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20201223173846031.png)]
get()
//源码
public T get() {
if (this.value == null) {
throw new NoSuchElementException("No value present");
} else {
return this.value;
}
}
使用get方法获取到的就是具体的值
Optional<String> optional = Optional.of("123");
System.out.println(optional.get());
//获取到的值是:123
ofNullable
//源码
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
如果不是null 就返回自己的值 反之创建 Optional对象
Optional<String> optional = Optional.ofNullable(null);//如果不是null 就会返回Optional[传入的值]
System.out.println(optional);//Optional.empty
ifPresent
判断值是否为null 不为null就返回 为null就不管
Consumer
//源码
public void ifPresent(Consumer<? super T> action) {
if (this.value != null) {
action.accept(this.value);
}
}
如果传入Optional的值不为null 那么就会使用我们传入(consumer接口)的
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
Optional<List<Integer>> optional = Optional.ofNullable(integers);
//lambda使用
optional.ifPresent(t-> System.out.println(t));
//对象::方法
optional.ifPresent(System.out::println);
//上面两种遍历方式效果都一样 只是使用方式不同
isPresent
//源码
public boolean isPresent() {
return this.value != null;
}
判断Optional是否为空 为空就会返回false 反之返回true
Optional<String> optional = Optional.ofNullable("abc");//传入的是null 返回的就是false 反之true
boolean present = optional.isPresent();
map
Function
public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
return !this.isPresent() ? empty() : ofNullable(mapper.apply(this.value));
}
map主要是配合着(Function接口)来使用
判断传入map的值是否为空 空就创建Optional
Optional<List<Integer>> optional = Optional.ofNullable(integers);
//不为空 就执行括号里面的lambda方法
Optional<String> optionalS = optional.map(t -> "abc");
filter
Predicate接口
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!this.isPresent()) {
return this;
} else {
//在这里就是使用Predicate接口
return predicate.test(this.value) ? this : empty();
}
}
String str = "132";
Optional<String> optional = Optional.ofNullable(str);//如果Optional为空会执行 if的语句 反之执行else的语句
//这里就是predicate接口的具体实现
Predicate<String> predicate = t->true;//这里的值决定 predicate.test(this.value)的值
Optional<String> optionalS = optional.filter(predicate);
System.out.println(optionalS);
orElse
public T orElse(T other) {
return this.value != null ? this.value : other;
}
Cat cat_1 = new Cat(1,"第一只",10);
Cat cat_2 = new Cat(2,"第二只",20);
Cat cat_3 = new Cat(3,"第三只",30);
List<Cat> cats = Arrays.asList(cat_1, cat_2, cat_3);
// Person person = new Person(1, "张三", cats);
Person person = new Person();
//传入值
Optional<Person> optional = Optional.ofNullable(person);
//获取到person类里面的 list集合 orElse判断集合是否是null 是null就执行方法括号里面的内容
List<Cat> cats1 = optional.map(Person::getCatList).orElse(Collections.emptyList());
System.out.println(cats1);
//该方法的作用是 提供一个空的list集合
Collections.emptyList()
Cat类
private Integer id;
private String name;
private Integer age;
Person类
private Integer id;
private String name;
private List<Cat> catList;
orElseGet
Supplier
public T orElseGet(Supplier<? extends T> supplier) {
return this.value != null ? this.value : supplier.get();
}
判断Optional是否为null 不为空就注解把值返回回去 为空就值Supplier接口被实现的方法
Optional<String> optional = Optional.ofNullable("123");//如果传入的是null 那么最后打印的是abc 反之打印123
String s = optional.orElseGet(() -> "abc");
System.out.println(s);
案例
String str = "abc";
Optional<String> optional = Optional.ofNullable(str);
String main = optional.filter(
t -> !(t.equals(""))).map(
t -> "123").orElseGet(
() -> "login");
System.out.println(main);
Stream
常用方法
skip 跳过
concat合并流
limit 分页
distinct 去重
sorted 排序
parallel 并行
findFirst 获取到数组的第一个元素
findAny 获取到运行时第一个元素
count 计数
需要注意的是Map集合不能直接调用stream 需要Stream的of方法来转换
集合
//List Stream
List<Integer> integers = Arrays.asList(10, 20, 30, 40, 50);
Stream<Integer> stream1 = integers.stream();
//set
Set<Integer> set = new HashSet<>();
Stream<Integer> stream = set.stream();
//map map不能直接调用stream方法 想要转为流 需要Stream的of方法
Map<String,Integer> map = new HashMap();
Stream<Map<String, Integer>> map1 = Stream.of(map);
数组
//数组集合
//Integer
Integer[] integers1 = new Integer[]{1,2,3,4,5};
Stream<Integer> stream3 = integers.stream();
//int
int[] ints = new int[]{1,2,3};
IntStream stream4 = Arrays.stream(ints);
//string
String[] strings = new String[]{"a","b","c","d"};
Stream<String> stream2 = Arrays.stream(strings);
of方法
//Stream调用of方法
Stream<int[]> ints1 = Stream.of(ints);
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4);
Stream<String> a = Stream.of("a", "b");
Stream的中间操作与终结操作
终结操作和中间操作的区别
中间操作:流从源头到结束的过程中所进行的操作 都为中间操作 并且只要不执行终结操作,那么流就一直会执行。
终结操作:使用了终结操作,那么流就结束了,不能在执行中间操作**
常用的终结操作有:forEach,ifPresent
在不使用终结操作
public static void main(String[] args) {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6);
Stream<Integer> stream = integers.stream().filter(num -> num >= 3);
Stream<Integer> integerStream = stream.filter(num -> num < 6);
integerStream.forEach(System.out::println);
}
使用终结操作后再继续继续中间操作
public static void main(String[] args) {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6);
Stream<Integer> stream = integers.stream().filter(num -> num >= 3);
stream.forEach(System.out::println);//终结操作
Stream<Integer> integerStream = stream.filter(num -> num < 6);
integerStream.forEach(System.out::println);
}
串行与并行
findFirst
Stream.of(1,3,4,2,67,25).parallel() //把串行该为并行
.findFirst() //获取到数组的第一个元素
.ifPresent(System.out::println);
findAny
Stream.of(3,4,64,16,431,4).parallel()
.findAny() //获取到运行时第一个元素
.ifPresent(System.out::println);