赞
踩
意义:
简化匿名类的编码
减少不必要的方法创建
例子:Java7
和Java8
匿名实现接口对比
public static void main(String[] args) { // Java7 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(i); } } }).start(); // Java8 new Thread(() -> { for (int i = 0; i < 100; i++) { System.out.println(i); } }).start(); }
只有一个抽象方法的接口称为函数式接口,通常会贴上@FunctionalInterface
注解表示其是一个函数式接口,加了此注解之后, 抽象方法就只能有一个 ,但 默认方法可以有多个
例子:
首先定义一个功能性接口,定义一个抽象方法
@FunctionalInterface
public interface Person{
void say();
}
调用接口方法
① 传统做法需要创建一个实现类去实现接口的抽象方法
// 创建实现类实现接口 public class PersonImpl implement Person{ @Override public void say(){ System.out.println("Hello"); } } // new 一个实现类对象调用方法 public class Demo{ public static void main(String[] args){ //接口引实现类 Person person = new PersonImpl(); //调用方法 person.say(); } }
② 或者使用匿名内部类的方式实现调用
public class Demo{
public static void main(String[] args){
Person person = new Person(){
@Override
public void say(){
System.out.println("Hello");
}
};
person.say();
}
}
③ 基于函数式接口内部只有一个抽象方法,可以用lambda
语法简化匿名内部类的书写
public class Demo{
public static void main(String[] args){
Person person =() -> {
System.out.println("Hello");
}
}
}
因为接口里面就一个抽象方法,所以默认就执行这一坨固定格式,不用你写
new Person(){ @Override public void say(){} };
- 1
- 2
- 3
- 4
你需要指定给我的是参数和方法体
()
表示参数列表
{}
表示方法体逻辑
如果抽象方法有参数:
void say(String msg);
//指定参数名(不需要指定参数类型,在抽象方法中已经定义好了),给定方法体(实现逻辑)
public class Demo{
public static void main(String[] args){
Person person =(msg) -> {
System.out.println("Hello"+msg);
}
person.say("World");
}
}
如果方法体逻辑只有一句,{}可以省略:
public class Demo{
public static void main(String[] args){
Person person =(msg) -> System.out.println("Hello"+msg);
person.say("World");
}
}
如果方法体实现逻辑只有一个return语句,return也可以省略掉:
public class Demo{
public static void main(String[] args){
Person person =(msg) -> "Hello"+msg;
person.say("World");
}
}
访问局部变量 |
---|
Lambda表达式可以访问外部的局部变量,且该变量可以不用final修饰,但必须保证在Lambda表达式调用该变量后,该变量值不变(隐义final) |
String msg = "1";//定义变量
Person person =(msg) -> "Hello"+msg;//调用该变量
msg = "2";//报错,变量被Lambda表达式调用后不能变
访问字段和静态变量 |
---|
Lambda表达式对外部的字段和静态变量都有读写权限,和匿名内部类一样 |
访问接口的默认方法 |
---|
Predicate< T > 断言接口 |
---|
抽象方法 : boolean test(T t); |
接口特点 : 自定义参数类型,返回值固定为boolean |
Function<T, R> 功能接口 |
---|
抽象方法 : R apply(T t); |
接口特点 : 自定义参数类型,自定义返回值类型 |
Supplier< T > 生产接口 |
---|
抽象方法 : T get(); |
接口特点 : 无参数,自定义返回值类型 |
Consumer< T > 消费接口 |
---|
抽象方法 : void accept(T t); |
接口特点 : 自定义参数类型,无返回值 |
Comparator< T > 比较接口 |
---|
抽象方法 : int compare(T o1, T o2); |
接口特点 : 自定义参数类型,返回int型值 |
说明 : 比较两个指定参数,当前者>后者的时候,返回一个正数,当前者<后者的时候,返回负数,相等的时候返回0 |
流式处理主要针对集合,数组和文件,把对象转成流使操作更简洁
例子 :把nums
集合中的所有偶数筛选出来存到一个新集合中
传统循环:
List<Integer> nums = Arrays.asList(1,2,3,4,5,6,7,8,9);
List<Integer> evens = new ArrayList<>();
for (final Integer num : nums) {
if (num % 2 == 0) {
evens.add(num);
}
}
流式处理:
List<Integer> evens = nums.stream()//转流
.filter(num -> num % 2 == 0)//中间操作(过滤)
.collect(Collectors.toList());//终端操作(转List集合)
解析:
stream()
操作将集合转换成一个流,
filter()
执行我们自定义的筛选处理,这里是通过lambda
表达式筛选出所有偶数,
最后我们通过collect()
对结果进行封装处理,
并通过Collectors.toList()
指定其封装成为一个List集合返回。
filter过滤器
//调用了断言接口,对元素进行判断
//返回一个由处理结果组成的流对象
Stream<T> filter(Predicate<? super T> predicate);
map映射器
//调用了功能接口,对流元素进行一一映射处理(如每个元素+1,*10...)
//返回一个由处理结果组成的流对象
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
自然排序
//返回一个自然排序后的流对象
Stream<T> sorted();
自定义排序
//调用了比较接口,对流元素进行指定的比较操作
//返回排序后的流对象
Stream<T> sorted(Comparator<? super T> comparator);
去重
//返回对元素进行去重处理后的流对象
Stream<T> distinct();
递归
//对流元素进行递归操作(累加,累乘,累减...)
//内部逻辑
for (T element : this stream)
result = accumulator.apply(result, element)
return result;
//--------------------------
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
//调用消费接口,对所有元素进行消费处理(打印,输出)
//无返回值
void forEach(Consumer<? super T> action);
//把流封装成List集合并返回集合
<R, A> R collect(Collector<? super T, A, R> collector);
在collect()
中可以进行许多操作
现有一基于Person
对象的集合personList
[
Person(name=张三, age=20, Sex=男),
Person(name=李四, age=25, Sex=男),
Person(name=王五, age=30, Sex=男),
Person(name=小美, age=18, Sex=女),
Person(name=小红, age=25, Sex=女)
]
分组方法:Collectors.groupingBy()
,返回值是一个映射Map<K, List<T>>>
personList.stream()
.collect(Collectors.groupingBy(Person::getSex))
.forEach((k, v) -> System.out.println(k+":"+v));
女:[Person(name=小美, age=18, Sex=女), Person(name=小红, age=25, Sex=女)]
男:[Person(name=张三, age=20, Sex=男), Person(name=李四, age=25, Sex=男), Person(name=王五, age=30, Sex=男)]
personList.stream()
.collect(Collectors.groupingBy(Person::getSex,Collectors.summingInt(Person::getAge)))
.forEach((k, v) -> System.out.println(k+":"+v));
女:43
男:75
personList.stream()
.collect(Collectors.groupingBy(Person::getSex,Collectors.averagingInt(Person::getAge)))
.forEach((k, v) -> System.out.println(k+":"+v));
女:21.5
男:25.0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。