函数式接口
函数式接口:一般可以作为方法的参数和返回值类型
函数式接口:有且只有一个抽象方法的接口 函数式接口
接口也可以包含其他的方法(默认 静态 私有)
常见的函数接口
Consumer<T> 输出 accept(T t) 消费
Predicate<T> 判断 逻辑判断
Supplier<T> 生产 T get()
Function<T, R> 类型转换
接口用来根据一个类型数据得到另一个类型的数据
T 前置条件 R 后置条件
R apply(T t) 根据获取R结果
String 转换为Integer的整数
@FunctionalInterface
作用:可以检测接口是否是一个函数式接口
是:编译成功
否:编译失败(接口中没有抽象方法抽象方法的个数多于1个)
@FunctionalInterface
public interface MyFunctionalInterface {
void method();
}
lambda表达式
lambda特点: 延迟加载 使用前提 必须使用函数式接口
使用匿名内部类会产生class文件 使用lambda则不会 提高了效率
方法引用 lambda的优化
双冒号::
为引用运算符 表达式被称为方法引用
对象名引用成员方法
@FunctionalInterface
public interface Printable {
void method(String s);
}
/*
通过对象名引用成员方法
*/
public class MethodRefObject {
public void printUpperCase(String str){
System.out.println(str.toUpperCase());
}
}
/*
通过对象名引用成员方法
使用前提是对象名 成员方法已经存在
使用对象名引用成员方法
*/
public static void main(String[] args) {
//使用对象引用优化
MethodRefObject object =new MethodRefObject();
printString(object::printUpperCase);
}
数组构造器引用
@FunctionalInterface
public interface ArrayBuilder {
int[] creat(int length);
}
public static int[] creatArray(int length,ArrayBuilder builder){
return builder.creat(length);
}
public static void main(String[] args) {
/*
使用方法引用优化
已知创建的是int[]数组
数组长度也是已知
根据int[]引用new 根据参数传递的长度创建数组
*/
int[] ints = creatArray(12, int[]::new);
System.out.println(ints.length);
}
super引用父类成员方法
@FunctionalInterface
public interface Greetable {
void method();
}
public class Human {
public void sayHello(){
System.out.println("Human Hello");
}
}
public class Son extends Human {
@Override
public void sayHello() {
System.out.println("son Hello");
}
public void green(Greetable greetable){
greetable.method();
}
public void show(){
// 使用super引用成员方法
// super是已经存在的
// 父类成员方法sayHello已经是存在的
green(super::sayHello);
}
Stream流
Stream(流)是一个来自数据源的元素队列
- 元素是特定类型的对象 形成队列 Stream(流) 按需计算
- 数据源流的来源 可以是集合 数组
- 获取stream流的两种方式
- 所有的单列集合Collection
- 静态方法Stream.of(…args) 传入可变参数 数组也可以
Map转换为单列集合Collection
管道流 只能消费一次 使用一次 使用后就关闭了
要不就使用返回新的Stream流 继续用新的Stream流 使用
- 常用方法
延迟方法:返回类型仍然是Stream
接口自身类型的方法 可以调用其他方法
终结方法:count
,forEach
不可以再调用流中的其他方法
// forEach 循环 forEach(Consumer<? super T> action) 消费
// filter过滤 Stream<T> filter(Predicate<? super T> predicate) 函数判断
Stream<String> rt = Stream.of("rt", "yu", "io", "pl", "er");
rt.filter((name) -> name.startsWith("r")).forEach(n -> System.out.println(n));
类型转换Map
/*
将流中的元素映射到另一个流中 可以使用Map方法
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Function apply方法 类型转换
*/
//获取一个Stream 流
Stream<String> stream = Stream.of("1", "2", "3", "56");
// 使用Map方法 类型转换
stream.map(s -> Integer.parseInt(s)).forEach(s -> System.out.println(s));
//统计个数 count() 终结方法
long count = Arrays.asList(3, 5, 6, 8, 5, 0, 32).stream().count();
System.out.println(count);
limit截取元素
limit用于截取流中的元素
Stream<T> limit(long maxSize); 传入要截取的个数n
延迟方法 会返回新的流 调用别的方法
Arrays.asList(2,4,57,8,9,0).stream().limit(3).forEach(s-> System.out.println(s));
skip
/*
skip:跳过元素
希望跳过前几个元素 可以使用skip方法截取后的一个流
Stream<T> skip(long n);跳过前几个元素
*/
Arrays.asList(2,4,57,8,9,0).stream().skip(1).forEach(s-> System.out.println(s));
concat
/*
Stream流 常用方法 concat:用于把流组合在一起
连个流类型要一致
<T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
*/
Stream<Integer> stream1 = Arrays.asList(2, 4, 57, 8, 9, 0).stream();
Stream<Integer> stream = Arrays.asList(2, 4, 57, 8, 9, 0).stream();
Stream.concat(stream,stream1).forEach(s-> System.out.println(s));