内部函数式接口
既然Lambda表达式需要配合函数式接口来使用,且在函数式接口中只有一个抽象方法,那么完全可以针对方法的参数个数,以及是否有返回值,来定义一些常用的函数式接口。至于参数类型和返回值类型,则可以使用泛型来表示。
Java 8在java.util.function包中,定义了许多函数式接口,下表列出了四个基本的函数式接口。
函数式接口 | 方法 | 用途 |
---|---|---|
Consumer< T > | void accept(T t) | 消费性接口 (有来无回),即有参数没有返回值 |
Predicate< T > | boolean test(T t) | 段言型,有参数,返回值为boolean类型 |
Function< T,R > | R apply(T t) | 函数型接口,有参数有返回值,皆为任意类型 |
Supplier | T get() | 供给型接口,无参数,有返回值 |
在编写代码时,可以根据内置的函数式接口中的方法参数个数、类型和返回值类型,选定一个函数式接口来应用Lambda表达式。
例如:要判断一个对象是否为null,无需自定义函数式接口,直接使用断言型接口Predicate
即可。
public static void main(String[] args) {
Predicate<String> p = (string)->{
if(string==null) {
return false;
}else {
return true;
}
};
boolean b1 = p.test("abc");
boolean b2 = p.test(null);
System.out.println(b1);
System.out.println(b2);
}
方法的引用
概念
通过方法的名字来指向一个方法,使语言的构造更紧凑简洁,减少冗余代码。
语法
方法名::方法
使用
package com.bigdata.practice1011;
import java.util.Arrays;
import java.util.List;
@FunctionalInterface
public interface Supplier<T>{
T get(); // 供给型函数式接口 无参数有返回值
}
class Car {
//Supplier是jdk1.8的接口,这里和lamda一起使用了
public static Car create(final Supplier<Car> supplier) {
return supplier.get();
}
public static void collide(final Car car) {
System.out.println("Collided " + car.toString());
}
public void follow(final Car another) {
System.out.println("Following the " + another.toString());
}
public void repair() {
System.out.println("Repaired " + this.toString());
}
/**
* 方法的引用举例
* 构造器:Class::new
* 静态方法:Class::static_method
* 特定类的任意对象:Class::method
* 特定对象的方法:instance::method
*
*/
public static void main(String[] args) {
// 构造---》 供给型函数式接口
final Car car = Car.create(Car::new); // 借助供给型函数式接口supplier<Car> su
final List<Car> cars = Arrays.asList(car);
for (Car car1 : cars) {
}
// 静态方法
cars.forEach(Car::collide);
cars.stream().forEach(System.out::println);
// 实例方法
cars.forEach(Car::repair);// 任意对象的任意方法
final Car po = Car.create(Car::new);
cars.forEach(po::follow); // 特定对象的方法
}
}
Stream的学习
简介:
lambda导入:
Lambda表达式是jdk1.8中一个重要的新特性。
-
lambda表达式允许你通过表达式来代替功能接口。
-
lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体。
-
在Lambda表达式中this是指外围实例,而匿名类中的this是指匿名类实例。
-
如果想在Lambda表达式里面修改外部变量的值也是可以的,可以将变量定义为非局部变量,即为实例变量或者将变量定义为数组。
-
Lambda表达式如果引用某局部变量,则直接将其视为final。
-
1.lambda表达式没有命名,用来像传递数据一样传递操作。
-
2.函数接口指的是只有一个抽象方法的接口,被当做是lambda表达式的类型。最好使
@FunctionalInterface
注解,防止其他人在里面添加方法。只需要在想要执行的地方利用传递的对象调用对应的接口中唯一的方法即可。
Lambda表达式还增强了集合库。
- jdk1.8添加了2个对集合数据进行批量操作的包:
java.util.function
包以及java.util.stream
包。 - 流(stream)就如同迭代器(iterator),但附加了许多额外的功能。
Stream介绍:
-
概念
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
-
理解
把Stream当成一个高级版本的Iterator。原始版本的Iterator,用户只能一个一个的遍历元素并对其执行某些操作;高级版本的Stream,用户只要给出需要对其包含的元素执行什么操作,比如“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,具体这些操作如何应用到每个元素上,就给Stream就好了。
抽象流Stream类:[结合lambda表达式来对数组或者集合的数据进行操作,并且不影响集合和数组里面的数据]
特点:
-
不是数据结构,不会保存数据。
-
不会修改原来的数据源,它会将操作后的数据保存到另外一个对象中。(保留意见:peek方法可以修改流中元素)
-
惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算
使用
步骤
- 创建流【Stream接口显示创建,也可以集合数组直接调用stream()方法创建并操作】
- 通过Stream接口的静态工厂方法
- 通过Collection接口的默认方法 -stream() 去转换
- 转换Stream,返回一个新的Stream对象【中间方法,可以多次操作不】
- 结束流【末端方法即聚合方法】
常用
* 抽象流Stream类的练习:[结合lambda表达式来对数组或者集合的数据进行操作,并且不影响集合和数组里面的数据]
* 1.创建流【Stream接口显示创建,也可以集合数组直接调用stream()方法创建并操作】
* 2.操作流【中间方法】
* 3.结束流【末端方法】
* 中间方法:
filter、过滤
* map、映射
* distinct、去重,需要注意equals和hashcode
* sorted、注意排序对象需要实现接口并重写方法
* limit、取前多少个
* 末端方法:min、max:最小最大值
* count:求总
* forEach():遍历
深入学习Stream流【记录】
equals和hashcode
-
sorted、注意排序对象需要实现接口并重写方法
-
limit、取前多少个
- 末端方法:min、max:最小最大值
-
count:求总
-
forEach():遍历
##### 深入学习Stream流【记录】