1、Lambda表达式
1、概述
(1)Lambda表达式是内部类的一种简写形式,对为提升代码开发效率对函数式接口的一种抽象实现的方式。
(2)好处:避免了很多无用或者说不需要的代码;
(3)Lambda表达式的专用符号**->通常称为箭头符号,或者是砖石操作符;
(4)在->**的左边是表达式的参数,在符号的右边是表达式的逻辑代码
(5)Lambda的语法格式
(1)语法格式一:没有返回值,没有参数的方法的语法结构;
()->{ 具体实现;};
例如:
准备一个只有一个抽象方法的接口
接口
package LambdaDemo;
public interface PrintDemo {
public void print();
}
测试类
package LambdaDemo;
import org.junit.jupiter.api.Test;
public class TestLambda {
@Test
public void test() {
PrintDemo pd=()->System.out.println("我是PrintDemo接口");
pd.print();
}
}
结果
注意:无参数时方法的参数的小括号不能省略;如果Lambda体只有一条语句,大括号可以省略,如果实多条语句不可以省略.
(2)语法格式二
有一个参数,没有返回值
方法的引用=(参数)->{ Lambda具体实现体 };
例如:
接口:
package LambdaDemo;
public interface Fun {
public void print(Object x);
}
测试类
public class TestLambda {
@Test
public void test() {
Fun fun=(x)->System.out.println("我是匿名内部类的实现,有一个参数"+x);
fun.print(20);
}
}
结果:
注意:对于只有一个参数的函数方法,小括号可以省略,如果Lambda体只有一条语句,此时大括号也可以省略
(3)语法格式三
有多个参数,没有返回值的方法
接口类型 变量名称=(x,y)->{ Lambda代码实体 };
例如:
接口:
public interface Fun {
public void print(Object x, Object y);
}
测试类
public class TestLambda {
@Test
public void test() {
Fun fun=(x,y)->System.out.println("我是匿名内部类的实现,有一个参数"+x+":"+y);
fun.print(20,30);
}
}
结果:
(4)语法格式四
有返回值,没有参数
接口:
public interface Fun {
public Object print();
}
测试类
public class TestLambda {
@Test
public void test() {
Fun fun=()->{System.out.println("我是匿名内部类的实现,无参数");return "返回一句话";};
System.out.println(fun.print());
}
}
结果
(5)语法格式五
有返回值,有参数
接口:
public interface Fun {
public Object print(Object x);
}
测试类
public class TestLambda {
@Test
public void test() {
Fun fun=(x)->{System.out.println("我是匿名内部类的实现,有一个参数");return x;};
System.out.println(fun.print(20));
}
}
结果
例题:用Lambda表达式实现传入两个参数,返回两个参数的和
接口:
public interface Fun {
public int print(int x,int y);
}
测试类
public class TestLambda {
@Test
public void test() {
Fun fun=(x,y)->{System.out.println("我是匿名内部类的实现,两个参数的和是:");return (x+y);};
System.out.println(fun.print(20,30));
}
}
结果
函数式接口
1、函数式接口是Lambda 表达式的前提。函数式接口是只有一个抽象方法的接口我们称之为函数值接口。
2、函数式接口可以使用@@FunctionalInterface注解进行验证,如果在一个接口上加上该注解不报错,那么该接口就是一个函数式接口。
3、函数接口的作用:接口只是对方法的声明,并可以作为一个类型来进行方法的调用,让接口的实现类能够指向该接口的类型,在java 中方法不能脱离类独立存在,但是函数可以独立存在,为了使Java中的方法具有和函数类似的功能,通过函数式接口,在接口中声明一个方法,此时,接口类型中的方法就一个,就相当声明了该类型的方法,此时该函数是接口可以作为参数来进行传递,让方法间接具有了函数的功能。
4、函数式接口是实现Lambda表达式的前提条件;函数式接口的定义:函数式接口的本质就是一个接口,只是该接口下只能有一个抽象方法。
JDK8常用的函数式接口
1、消费型函数式接口:有一个参数,无返回值
1、Consumer 泛型类型规定该接口方法参数的类型
2、接口方法:void accept(T t);
2、生产型函数式接口:无参数,有返回值
1、Supplier 泛型类型规定该接口方法返回值的类型
2、 T get();
3、函数型接口:参数是T类型的,返回值是R类型的
1、Function<T, R> ,第一泛型表示接口方法的参数类型,第二个泛型表示返回值类型
2、R apply(T t);
4、断言型接口:常用于判断和过滤,一个参数,返回值是布尔类型
1、Predicate
2、 boolean test(T t); 该方法返回的是boolean 值,主要用来过滤结果。
特性三:方法的引用
1、概述
在实现函数式接口方法的时候,如果函数式接口需要实现的方法的功能。包括方法的声明和已经在其他的类中定义好并完全一致,此时,就可以将已经实现好的方法引过来作为该函数式接口的实现方法。
2、语法格式
如果引用的方法是普通方法,则语法格式为 引用方法的类的对象 :: 方法名;
如果引用的方法是静态方法,则语法格式为 引用方法的类的类名 :: 方法名;
实例:
public void conTest() {
Consumer<Integer> co2 = new Consumer<Integer>() {
@Override
public void accept(Integer t) {
System.out.println(t);
}
};
//普通方法的引用
Consumer<Integer> co3 = new Demo() :: print;
co3.accept(45);
Consumer<String> co4 = new Consumer<String>() {
@Override
public void accept(String t) {
System.out.println(t);
}
};
//静态方法的引用
Consumer<String> co5 = Demo :: prin;
co3.accept(45);
}
class Demo{
public void print(int x) {
System.out.println(x);
}
public static void prin(String st) {
System.out.println("我是静态方法" + st );
}
}
特性四:Stream API
1、概述:
该方法提供一种对集合、数组、IO等类中数据以流的形式来操作的方式,提升程序的开发效率
2、该方法是jdk提供的,主要是Collection集合和数组
3、常用的方法
(1)filter(Predicate<? super T> predicate) 根据函数式接口提供的过滤规则对流中的元素进行过滤。
(2)concat(Stream<? extends T> a, Stream<? extends T> b) 将两个流对象拼接成一个流对象
(3)count() 统计流对象中元素的个数,返回long类型的个数
(4)distinct() 对流中数据进行去重
(5)forEach(Consumer<? super T> action) 对集合中元素进行遍历
(6)limit(long maxSize) 获取限定个数的流对象
(7)skip(long n) ;跳过n 个元素后获取剩余的元素
(8)sorted() 对流中元素进行排序。
实例:
public class SuppliTest {
@Test
public void SuppTest() {
Random ran=new Random();
Supplier<Integer>su=()->ran.nextInt(50)+30;
List<Integer>li=method(su,30);
System.out.println(li);
}
public List<Integer>method(Supplier<Integer>su,int num){
List<Integer>list=new ArrayList<Integer>();
for(int i=0;i<num;i++) {
list.add(su.get());
}
return list;
}
}
测试Stream API
产生随机数过滤并且打印:
public class StreamDemo {
@Test
public void ListStream() {
Random ran=new Random();
List<Integer>li=new SuppliTest().method(()->ran.nextInt(50)+30, 30);
//统计个数
Long l=li.stream().count();
//遍历集合中的元素
System.out.println(l);
li.stream().forEach(x->System.out.println(x+":"));
System.out.println();
li.stream().forEach(System.out::print);
System.out.println();
//对流中的元素进行过滤
li.stream().filter(x->x%2==0).forEach(x->System.out.println(x+":"));
}
}
特性五:NIO
1、概述
1、NIO 是jdk 1.4 之后提供一种更高级的IO 流操作方式,该种IO 是通过管道来对文件进行读写的,文件的整个读写过程都在文件管道中进行。
2、NIO 是非阻塞式的IO ,且NIO 可读可写。
3、在NIO 读写文件创建一个缓存区,数据的交换全部在缓存区进行。
4、IO 和NIO 的区别:
(1)IO 字节对磁盘文件进行读写操作,而NIO 的读写操作是在文件管道中进行的。
(2)IO 是阻塞式的读写方式,NIO 是非阻塞式的IO 读写。
(3)IO 是最原生的文件读写方式,NIO 在jdk 1.4 之后才有
(4)NIO 建立在IO 的基础之上,是更高效的IO 流。效率更高。
实例:利用NIO进行文件的复制操作