1、Lambda表达式
Lambda是java8的新特性,使用Lambda可以替代只有一个抽象方法的接口(函数接口)实现,类似于匿名内部类。
1.1 、Lambda的语法格式
()-> {}
- (): 用来描述参数列表。
- {}:用来描述方法体、执行语句,当只有一条执行语句或只有返回值的时候可以省略。
- -> :Lambda运算符
1.2、Lambda基本语法实例
创建多个接口
public interface LambdaInterface {
int test1();
}
@FunctionalInterface
public interface LambdaInterface1 {
int test2(int a);
}
@FunctionalInterface
public interface LambdaInterface2 {
int test3(int a,int b);
}
@FunctionalInterface
public interface LambdaInterface3 {
void test4();
}
@FunctionalInterface
public interface LambdaInterface4 {
void test5(int a);
}
@FunctionalInterface
public interface LambdaInterface5 {
void test6(int a,int b);
}
测试类
public class LambdaTest {
public static void main(String[] args) {
/**
* 无参数,有返回值
*/
//LambdaInterface test = () ->{return 200;};
LambdaInterface test = () -> 200;
int i2 = test.test1();
System.out.println(i2);
/**
* 有单个参数,有返回值
*/
//LambdaInterface1 test2 = (int a) ->{return a;};
LambdaInterface1 test2 = a -> a;
int i3 = test2.test2(200);
System.out.println(i3);
/**
* 有多个参数,有返回值
*/
//LambdaInterface2 test3 =(int a ,int b) -> {return a-b;};
LambdaInterface2 test3 =(a,b) -> a-b;
int i = test3.test3(20, 1);
System.out.println(i);
/**
* 有参数,无返回值
*/
// LambdaInterface4 test4 = a -> {System.out.println(a);};
LambdaInterface4 test4 = a -> System.out.println(a);
test4.test5(12);
/**
* 有多个参数,无返回值
*/
//LambdaInterface5 test5 = (a, b) ->{System.out.println("a="+a+" b="+b);};
LambdaInterface5 test5 = (a, b) -> System.out.println(a+b);
test5.test6(12,24);
/**
* 无参数,无返回值
*/
LambdaInterface3 test6 = () -> System.out.println("无参数,无返回值!");
test6.test4();
}
}
输出结果
1.3、Lambda的方法引用
方法引用:若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用(可以理解为方法引用是Lambda表达式的另一种表现形式)
主要有三种语法格式:
对象::实例化方法名
类::静态方法名
类::实例方法名
注意:1、Lambda体中调用方法的参数列表于返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!
2、若Lambda参数列表中的第一参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以ClassName::method
//对象::实例方法名
@Test
public void test1(){
//Consumer<String> con1 =(x) -> System.out.println(x);
Consumer<String> con = System.out::println;
con.accept("adcdef");
}
//类::静态方法名
@Test
public void test2(){
//Comparator<Integer> com = (x ,y) ->Integer.compare(x,y);
Comparator<Integer> com1 = Integer::compare;
}
//类::实例方法名
@Test
public void test3(){
//BiPredicate<String,String> bp =(x,y) -> x.equals(y);
BiPredicate<String,String> bp =String::equals;
}
//数组引用
@Test
public void test4(){
//Function<Integer,String[]> fun =(x) ->new String[x];
Function<Integer,String[]> fun = String[]::new;
String[] strs = fun.apply(10);
System.out.println(strs.length);
}
}
输出结果
1.4、方法引用(构造函数)
创建实体类
public class Person {
public String name;
public int age;
public Person(){
System.out.println("这是无参构造方法");
}
public Person(String name,int age){
System.out.println("这里是有参构造");
this.name=name;
this.age=age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
创建接口
interface LambdaInterfaceTest{
Person getPerson();
}
interface LambdaInterfaceTest1{
Person getPerson(String name,int age);
}
测试类
public class LambdaTest2 {
public static void main(String[] args) {
LambdaInterfaceTest test = ()-> new Person();
test.getPerson();
//构造方法的引用
LambdaInterfaceTest test1 = Person::new;
test1.getPerson();
LambdaInterfaceTest1 test11 =Person::new;
test11.getPerson("lzf",12);
}
}
输出结果
2、函数式接口
1、Lambda表达式使用前提,接口必须是一个函数接口
2、函数式接口(FunctionalInterface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
3、函数式接口可以被隐式转换为 lambda 表达式。
4、 Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上
5、使用注解@FunctionalInterface
四大内置核心函数接口
public class Lambda5 {
//Supplier<T>
@Test
public void test1(){
List<Integer> numList = getNumList(10, () -> (int) (Math.random() * 100));
for (Integer n:numList) {
System.out.print(n+" ");
}
}
//需求:产生指定个数的整数,并放入集合中
public List<Integer> getNumList(int num, Supplier<Integer> sup){
List<Integer> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
Integer n = sup.get();
list.add(n);
}
return list;
}
@Test
//Predicate<T>
public void test2(){
List<String> list = Arrays.asList("kzf","sdad","sdada","hwidh");
List<String> strings = filterStr(list, (s -> s.length() > 3));
for (String a:strings) {
System.out.print(a+" ");
}
}
//将满足条件的字符串,放入集合中
public List<String> filterStr(List<String> list, Predicate<String> pre){
List<String> list1 = new ArrayList<>();
for (String a: list) {
if(pre.test(a)){
list1.add(a);
}
}
return list1;
}
//Consumer<T> :处理字符串
@Test
public void test3(){
nihao("dci",(m)-> System.out.println("你好"+m));
}
public void nihao(String name, Consumer<String> con){
con.accept(name);
}
//Function<T,R>函数型接口:
@Test
public void test4(){
String s = strHandler("\t\t\t你好我他", (str) -> str.trim());
System.out.println(s);
}
public String strHandler(String str, Function<String,String> fun){
return fun.apply(str);
}
}
输出结果
1、22 30 82 84 54 49 62 38 55 2
2、sdad sdada hwidh
3、你好dci
4、你好我他
系统内置的一些函数式接口
public class FunctionalInterface {
public static void main(String[] args) {
// Predicate<T> : 参数是T 返回值boolean
// 在后续如果一个接口需要指定类型的参数,返回boolean时可以指向 Predicate
// IntPredicate int -> boolean
// LongPredicate long -> boolean
// DoublePredicate double -> boolean
// Consumer<T> : 参数是T 无返回值(void)
// IntConsumer int ->void
// LongConsumer long ->void
// DoubleConsumer double ->void
// Function<T,R> : 参数类型T 返回值R
// IntFunction<R> int -> R
// LongFunction<R> long -> R
// DoubleFunction<R> double -> R
// IntToLongFunction int -> long
// IntToDoubleFunction int -> double
// LongToIntFunction long -> int
// LongToDoubleFunction long -> double
// DoubleToLongFunction double -> long
// DoubleToIntFunction double -> int
// Supplier<T> : 参数 无 返回值T
// UnaryOperator<T> :参数T 返回值 T
// BiFunction<T,U,R> : 参数 T、U 返回值 R
// BinaryOperator<T> :参数 T、T 返回值 T
// BiPredicate<T,U> : 参数T、U 返回值 boolean
// BiConsumer<T,U> : 参数T、U 无返回值
/**
* 常用的 函数式接口
* Predicate<T>、Consumer<T>、Function<T,R>、Supplier<T>
*/
}
}
3、Stream Api
创建stream的几种方法
public class LambdaTest6 {
@Test
public void test1(){
//创建Stream
//1、可以通过Collection系列集合提供的stream()或parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
//2.通过Stream类中的静态方法of()
Stream<String> aa = Stream.of("aa", "bb", "cc");
//3.通过Arrays中的静态方法stream()获取数据流
Person[] person = new Person[10];
Stream<Person> stream1 = Arrays.stream(person);
//4.创建无限流
Stream<Integer> iterate = Stream.iterate(0, (x) -> x + 2);
iterate.limit(10).forEach(System.out::println);
//5.生成
Stream.generate(()->Math.random()*100).limit(10).forEach(System.out::println);
}
生成测试数据
List<Person> personList = Arrays.asList(
new Person("张三", 14),
new Person("李四", 28),
new Person("王五", 38),
new Person("张三", 59),
new Person("张三", 75),
new Person("张三", 75),
new Person("张三", 75)
);
筛选和切片
//filter --接受Lambda,从流中排出某些元素
@Test
public void test1() {
Stream<Person> stream = personList.stream()
.filter((e) -> e.getAge() > 30);
stream.forEach(System.out::println);
}
/**
* 运行结果
* Person{name='王五', age=38}
* Person{name='张三', age=59}
* Person{name='张三', age=75}
* Person{name='张三', age=75}
* Person{name='张三', age=75}
*/
//limit--截断流,使其元素不超过给定数量
@Test
public void test2() {
personList.stream()
.filter((e) -> e.getAge() > 30)
.limit(2)
.forEach(System.out::println);
}
/**
* 运行结果
* Person{name='王五', age=38}
* Person{name='张三', age=59}
*/
//skip(n)跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与 limit(互补)
@Test
public void test3() {
personList.stream()
.filter((e) -> e.getAge() > 30)
.limit(2)
.skip(1)
.forEach(System.out::println);
}
/**
* 运行结果
Person{name='张三', age=59}
*/
//distinct --筛选,通过流所生成元素的hashCode()和equals()去除重复元素
@Test
public void test4() {
personList.stream()
.filter((e) -> e.getAge() > 30)
.limit(2)
.skip(1)
.distinct()
.forEach(System.out::println);
}
/**
* 运行结果
Person{name='张三', age=59}
*/
排序
@Test
@Test
//自然排序
public void test5(){
List<Integer> list = Arrays.asList(1,2,3,4,5);
list.stream()
.sorted()
.forEach(System.out::println);
}
/**
* 运行结果
* 1
* 2
* 3
* 4
* 5
*/
查找 / 匹配
//findAny()和findFist()获取第一条数据,如果没有就返回为空。
@Test
public void test6() {
Person person = personList.stream()
.filter((e) -> e.getAge() > 30)
.limit(2)
.findAny()
.orElse(null);
System.out.println(person);
}
/**
* 运行结果
* Person{name='王五', age=38}
*/
//map(T -> R):使用map取出姓名(字符串)
@Test
public void test7(){
personList.stream()
.map(Person::getName)
.forEach(System.out::println);
}
/**
* 运行结果
* 张三
* 李四
* 王五
* 张三
* 张三
* 张三
* 张三
*/
判断方法
- 判断List集合中是否有一个元素包含姓名为张三的元素
- 判断List集合中是否所有实体名称都包含"张"这个字段。
- 判断List集合中是否存在不包含"张"这个字段。
@Test
public void test8(){
boolean result = personList.stream().anyMatch((person -> person.getName().equals("张三")));
boolean result1 = personList.stream().allMatch(person -> person.getName().contains("张"));
boolean result2 = personList.stream().noneMatch(person -> person.getName().contains("张"));
System.out.println(result);
System.out.println(result1);
System.out.println(result2);
}
/**
* 运行结果
* true
* false
* false
*/
统计方法
- reduce((T, T) -> T) 和 reduce(T, (T, T) -> T)
@Test
public void test9(){
Integer max = personList.stream().map(Person::getAge).reduce(Integer::max).get();
Integer min = personList.stream().map(Person::getAge).reduce(Integer::min).get();
Integer sum = personList.stream().map(Person::getAge).reduce(0,Integer::sum);
System.out.println(max);
System.out.println(min);
System.out.println(sum);
}
/**
* 运行结果
* 75
* 14
* 364
*/