接口特性(jdk8)
前:接口中只能定义:抽象方法和常量
后:
1. 新增可以添加默认方法
格式: default 返回值类型 方法名(参数列表){
…
return 返回值;
}
该方法会被实现类继承,实现类可以对这个方法重写也可以不重写。
特点:
1.实现多个接口,这些接口中有相同的方法声明,子类必须实现该方法,否则子类是抽象类,只需实现一次即可。
2.实现多个接口,这些接口中有相同的默认方法声明,方法体不同,要求实现类必须对这个默认方法进行重写。
在实现类中想要调用某个父接口中的默认方法:父接口名.super.默认方法名();
3.继承一个父类,实现多个接口,父类和接口中有相同的方法声明,方法体不同,子类可以重写该方法,也可以不重写,
但是默认是类优先原则。即:类是亲的,接口是干亲
2. 新增可以添加静态方法,也带有方法体
注意:这个方法不被实现类继承,想要方法只能通过接口类名访问。
接口与抽象类很像,继承关系会增强类与类间的耦合度;接口可以弱化耦合度,因此接口使用越来越广泛。
Lambda表达式
前提:接口中只能有一个抽象方法。
理解:其实就是一个对象,是一个实现类对象,是匿名内部类对象的一个简写格式。
格式:
() -> 语句体;
(抽象方法参数列表) -> {抽象方法实现语句};
() : 接口中抽象方法的参数列表
-> : 符号,将参数列表和语句体进行分割。
语句体: 抽象方法的实现代码。
总结格式:
public class Demo7 {
public static void main(String[] args) {
//匿名内部类对象
Runnable run = new Runnable() {
@Override
public void run() {
System.out.println("run");
}
};
new Thread(run).start();
//Lambda表达式
Runnable run1 = () -> System.out.println("run1");
new Thread(run1).start();
//方法是:void 无参数列表
//InterA a = () -> System.out.println("show");
//方法是: void 一个参数
//参数类型根据上下文可以推断出类型,因此可以省略
//参数个数只有一个,可以省略小括号
//InterA a = x -> System.out.println(x);
//方法是: void 两个或两个以上的参数
//InterA a = (x,y) -> System.out.println(x+y);
//方法是: 有返回值类型 有一个参数
//语句体::只有一行语句时,可以省略大括号。包括return在内,只有一行语句大括号和return都可以省略。
//如果体语句有大于等于两行一行,那么必须写大括号且
//InterA a = s -> {return s;};
InterA a = s -> {
for (int i = 0; i <10 ; i++) {
System.out.println(i);
}
return s;
};
}
}
interface InterA{
//void show();
//void method(int x);
//void method(int x,double y);
String function(String s);
}
函数式接口
能使用Lambda表达式前提是:接口中只能有一个抽象方法。
这样的接口:叫做函数式接口。
可以通过注解:@FunctionalInterface 来检验是否是函数式接口
注意该注解要写在关键字interface的上边。
注意:在函数式接口中可以有其他的默认方法或静态方法。
自定义:
核心函数式接口:
java.util.function包
消费型接口 Consumer <T>
void accept(T t) : 对接收的数据 t 进行操作,操作后不需要返回。
断言型接口
Predicte
void test(T t) : 对接收的数据t进行判断操作,结果是true或false
供给型接口 Supplier <T>
T get(): 不接受数据,直接返回数据
函数型接口 Function <T,R>
R apply(T t) : 接收 t 数据,进行操作,返回R类型的结果。
方法代码
//Consumer<T>
//void accept(T t)
//有一个参数,没有返回值,用来操作数据
Consumer<Integer> con = in -> System.out.println(in+3);
con.accept(13);
//Predicate<T>
//boolean test(T t)
//有一个参数,返回值为布尔型,用来判断数据
Predicate<String> pre = s -> s.equals("nihao");
System.out.println(pre.test("hello"));
//BiPredicate<T,R>
//boolean test(T t,R r)
//有两个参数,返回值为布尔型,用来判断数据
BiPredicate<String, String> bi = (s1,s2) -> s1.equals(s2);
System.out.println(bi.test("java", "hello"));
//Supplier<T>
//T get()
//没有参数,直接返回定义类型的数据
Supplier<String> sup = () -> "java".toLowerCase();
System.out.println(sup.get());
//Function<T,R>
//R apply(T)
//有一个属于第一个类型的参数,返回值为第二个参数
Function<String, Integer> fun = s -> s.length();
System.out.println(fun.apply("helloworld"));
andThen and or negate
//将字符串转为大写形式
// void accept(String s)
Consumer<String> con = s -> System.out.println(s.toUpperCase());
//con.accept("abced");
//Consumer andThen(Consumer)
//先执行调用者,在执行参数 ,对某个数据做连续操作
con.andThen(s -> System.out.println(s.length())).accept("abcdd");
//判断字符串的长度是否是5个
//boolean test(String s)
Predicate<String> pre = s -> s.length() == 5;
//System.out.println(pre.test("12345"));;
//Predicate and(Predicate)
//左边和参数进行与运算
System.out.println(pre.and( s-> s.startsWith("aaa")).test("aaaaa")); //true
//Predicate or(Predicate)
//左边和参数进行或运算
System.out.println(pre.or( s-> s.startsWith("aaa")).test("aaaaa")); //true
//Predicate negate()
//对原来结果的取反运算
System.out.println(pre.negate().test("aaaaa")); //false
//返回字符串的长度
//Integer get()
Supplier<Integer> sup = () -> "helloworld".length();
System.out.println(sup.get());
//字符串转为整型
//Integer apply(String s)
Function<String, Integer> fun = s -> Integer.parseInt(s);
//System.out.println(fun.apply("999"));
//先计算左边,使用左边的结果再计算右边 ,连续计算
//Function andThen(Function)
System.out.println(fun.andThen(num -> num * 10).apply("1024"));
//判断字符串是否相同
BiPredicate<String, String> bipre = (s1,s2) -> s1.equals(s2);
System.out.println(bipre.test("zhangsan", "lisi"));
方法引用
可以认为是Lambda表达式的另外一种体现形式。
当Lambda表达式中的 {语句体} 中的代码,某个方法的实现已经被某个对象给实现了,那么就可以使用方法引用的形式来写,这样可以简化代码。
方法引用相当于是抽象方法的实现赋值给接口类型的引用。
格式:
对象名 :: 实例方法名;
类名 :: 静态方法名;
类名 :: 实例方法名;
StreamAPI
Stream:可以对数据源进行我们想要的操作,如过滤、去重等操作。
数据源:集合或数组
注意:Stream仅仅是封装算法,对数据源数据进行计算,但是不会改变数据源数据,
计算后得到的是新的结果集
步骤:
1.获取Stream对象
2.对数据源进行一系列操作(多个操作)
3.终止操作
注意:只有看到终止操作,才会对数据进行计算操作,因此是一个延迟执行的动作。
1、获取Stream对象
Collection : stream()
Map : keySet().stream()
entrySet().stream()
数组: Stream.of()
2、中间操作
filter(Predicte ) :根据Predicte 进行过滤
distinct(): 对数据进行去重
limit(long num) :获取从1到num个数据
skip(long num):跳过num个数据,从num到末尾
map(Function) :对数据源数据进行指定(Function)的操作
3、终止操作
foreach(Consumer) : 按照consumer对数据进行终止操作
long count() : 统计计算后的结果集数据的个数
注意:没有中间操作可以直接进行终止操作。