简介:
lambda是一个匿名函数,也可以理解为接口的实例,一段可以像数据一样传递的代码,使Java语言更灵活,更紧凑
使用了新的语法操作符 ‘->’ ,该操作符的左侧是lambda表达式的参数部分,右侧是lambda体
* 格式一:无参,无返回值
* () -> System.out.println("hello lambda");
*
* 格式二:一个参数,无返回值(如果只有一个参数,则小括号可以不写:x -> System.out.println(x);)
* (x) -> System.out.println(x);
*
* 格式三:两个或以上的参数,有返回值,具lambda体中有多行语句,则需要放在{}中
* Comparator<Integer> comparator = (x,y) -> {
* System.out.println("格式三 hello");
* return x-y;
* };
* 格式四:如果lambda体中只有一条语句,则return和大括号{}可以不写
* Comparator<Integer> comparator1 = (x,y) -> Integer.compare(x,y);
*
* 格式五:lambda表达式的参数类型可以省略不写,JVM编译器可以根据上下文判断参数类型;
* lambda表达式需要函数式接口的支持
* 函数式接口:只有一个抽象方法的接口,可以使用@FunctionalInterface来检查是否是函数式接口,有该注解 修饰的接口,只能有一个抽象方法
*
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("hello world");
}
};
r.run();
System.out.println("===========");
Runnable r1 = () -> System.out.println("hello lambda");
r1.run();
System.out.println("格式二=====================");
Consumer<String> con = (x) -> System.out.println(x);
con.accept("hello 格式二");
System.out.println("格式三=====================");
Comparator<Integer> comparator = (x,y) -> {
System.out.println("格式三 hello");
return Integer.compare(x,y);
};
Comparator<Integer> comparator1 = (x,y) -> Integer.compare(x,y);
System.out.println("func=====================");
Integer num = operation(10, (x) -> x*x );
System.out.println(num);
}
只包含一个抽象方法的接口,是函数式接口,可以通过lambda表达式来创建该接口的对象,可以使用@FunctionalInterface注解来检查一个接口是否是函数式接口
//Collections.sort()通过这个方法,对emps进行排序,先按年龄排序,年龄相同按姓名比
public static void test(){
Collections.sort(emps,(e1,e2) -> {
if(e1.getAge() == e2.getAge()){
return e1.getName().compareTo(e2.getName());
} else {
return Integer.compare(e1.getAge(),e2.getAge());
}
});
for(Employee emp: emps){
System.out.println(emp.toString());
}
}
public class TestLambda4 {
public static void main(String[] args) {
Comsume con = new Comsume();
double money = 1000.0;
con.test(money,(x)-> System.out.println("消费:"+x));
Supply supply = new Supply();
Integer num = 10;
List<Integer> list = supply.getList(num, () -> (int) (Math.random() * 10));
System.out.println(list.toString());
Predict predict = new Predict();
boolean test = predict.test(120, (x) -> 100 < x && x < 200);
System.out.println(test);
}
}
//消费型接口
class Comsume{
public void test(double money, Consumer<Double> consumer){
consumer.accept(money);
}
}
//供给型接口
class Supply{
//产生指定个数的整数,并放入到集合中
public List<Integer> getList(Integer num, Supplier<Integer> supplier){
List<Integer> list = new ArrayList<>();
for (int i=0;i<num;i++){
Integer integer = supplier.get();
list.add(integer);
}
return list;
}
}
//断言型接口
class Predict{
//判断所给数据,是否在某个范围内
public boolean test(Integer num, Predicate<Integer> predicate){
return predicate.test(num);
}
}
说明:若lambda体中内容有方法已经实现了,可以使用方法引用,可以理解为lambda的另一种表现形式
注意:lambda体中调用方法的参数列表与返回值类型,要与函数式接口抽象方法的参数和返回值一致;
若lambda体中,参数列表的第一个参数是实例方法的调用者,第二个参数是实例方法的参数时,可以使用 类名::实例方法名
方法引用:使用操作符 “::” 将方法名和对象或类的名字分隔开来
三种情况:
构造器引用
格式:ClassName::new
注意:调用哪个构造器,取决于函数式接口的抽象方法的参数,根据参数列表取决于调用哪个构造方法;
class Test1{
//对象 :: 实例方法
public void test01(String str){
//Consumer consumer = (x) -> System.out.println(x);
Consumer<String> consumer1 = System.out::println;
consumer1.accept(str);
}
//对象 :: 实例方法
public Integer getAge(){
Employee emp = new Employee();
Supplier<Integer> supplier = emp::getAge;
return supplier.get();
}
//类 :: 静态例方法
public void test03(){
// Comparator comparator = (x,y)-> Integer.compare(x,y);
Comparator<Integer> comparator = Integer::compare;
int compare = comparator.compare(10, 20);
System.out.println(compare);
}
//类 :: 实例方法
//若lambda体中,参数列表的第一个参数是实例方法的调用者,第二个参数是实例方法的参数时,可以使用 类名::实例方法名
public void test04(){
BiPredicate<String,String> bp = (x,y)->x.equals(y);
BiPredicate<String,String> bp1 = String::equals;
}
//构造器引用
public void test05(){
Supplier<Employee> sp = ()-> new Employee();
Supplier<Employee> sp1 = Employee::new;
sp1.get();
}
public void test06(){
Function<Integer,String[]> f = (x)->new String[x];
Function<Integer,String[]> f1 = String[]::new;
String[] apply = f1.apply(10);
System.out.println(apply.length);
}
}
说明:流是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列,集合讲的是数据,流讲的是计算!
注意:
Stream操作的三个步骤
创建流:一个数据源(如:集合、数组),获取一个流
/*创建流
Java8 中的 Collection 接口被扩展,提供了两个获取流的方法:
default Stream stream() : 返回一个顺序流
default Stream parallelStream() : 返回一个并行流
Java8 中的 Arrays 的静态方法 stream() 可以获取数组流
static Stream stream(T[] array): 返回一个流
有值创建流:可以使用静态方法 Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数
public static Stream of(T... values) : 返回一个流
有函数创建无限流:可以使用静态方法 Stream.iterate()和Stream.generate(), 创建无限流
public static Stream iterate(final T seed, final
UnaryOperator f)
public static Stream generate(Supplier s)
*/
public void test01(){
//通过Collection系列集合提供的stream()或者parallelStream()来获取流
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
//通过Arrays中的静态方法stream()获取数组流
String[] strs = new String[5];
Stream<String> stream1 = Arrays.stream(strs);
//通过Stream的静态方法of()获取
Stream<String> aa = Stream.of("aa", "bb", "cc");
//创建无线流
//迭代
Stream<Integer> iterate = Stream.iterate(0, (x) -> x + 2);
iterate.limit(20).forEach(System.out::println);
//生成
Stream<Double> generate = Stream.generate(() -> Math.random());
generate.forEach(System.out::println);
}
中间操作:一个中间操作链,对数据源的数据进行处理
中间操作可以连接起来形成一个流水线,中间操作不会执行任何处理,在终止操作时,执行全部处理
//中间操作
/*
筛选与切片
filter -- 接收lambda,从流中排除某些元素
limit -- 截断流,使其元素不超过给定的数量(如果过滤到)
skip(n) -- 跳过元素,返回一个排除掉前n个元素的流,如果元素个数不足n个,则返回一个空流,与limit(n) 对应
distinct -- 筛选,通过流所生成元素的hashcode()和equals()去除重复元素
映射:
map :接收lambda,将元素转换成其他形式或提取信息,接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素,
排序:
sorted():自然排序
sorted(Comparator com):订制排序
*/
public void test02(){
//中间操作可以连接起来形成一个流水线,中间操作不会执行任何处理,在终止操作时,执行全部处理
Stream<Employee> stream = emps.stream().filter(employee -> {
System.out.println("Stream 中间操作");
return employee.getAge() > 22;
});
stream.forEach(System.out::println);
}
public void test03(){
emps.stream()
.filter(employee -> {
System.out.println("短路");
return employee.getAge()>18;
})
.limit(2)
.forEach(System.out::println);
}
public void test04(){
emps.stream()
.filter((e) -> e.getAge()>22)
.skip(2)
.forEach(System.out::println);
}
//map映射
public void test05(){
List<String> list = Arrays.asList("aaa","bbb","ccc","ddd");
list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
emps.stream().map(employee -> employee.getName()).forEach(System.out::println);
}
//排序
public void test06(){
List<String> list = Arrays.asList("eee","bbb","aaa","ccc","ddd");
list.stream().sorted().forEach(System.out::println);
emps.stream().sorted( (emp1,emp2)-> {
if(emp1.getAge() == emp2.getAge()){
return emp1.getName().compareTo(emp2.getName());
}
return Integer.compare(emp1.getAge(),emp2.getAge());
}).forEach(System.out::println);
}
终止操作:一个终止操作,执行中间操作链,并产生结果
/*
* 查找与匹配
* allMatch:检查是否匹配所有元素
* anyMatch:检查是否至少匹配一个元素
* noneMatch:检查是否没有匹配所有元素
* findFirst:返回第一个元素
* findAny:返回任意元素
* count:返回元素总个数
* max:返回流中最大值
* min:返回流中最小值
*
* 规约:
* reduce(T identity, BinaryOprator) / reduce(BinaryOprator) :可以将流中的元素反复结合
* 起来,得到一个值
* map-reduce模式:map和reduce连用
*
* 收集:
* collect(Collector c):将流转为其他形式,接收一个Collector接口的实现,用于给stream中的元素做汇总的方法,Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set、Map)。但是 Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,
*/
class Test2{
List<Employee> emps = Arrays.asList(
new Employee(100,"张三",20,5000.00, Employee.State.BUSY),
new Employee(100,"李四",22,6000.00,Employee.State.FREE),
new Employee(100,"王五",20,7000.00,Employee.State.BUSY),
new Employee(100,"朱六",25,8000.00,Employee.State.VOCATION),
new Employee(100,"样七",26,9000.00,Employee.State.BUSY)
);
public void test(){
//allMatch匹配所有元素
boolean b = emps.stream().allMatch(e -> e.getState().equals(Employee.State.BUSY));
System.out.println(b);
//anyMatch是否至少匹配一个元素
boolean b1 = emps.stream().anyMatch(e -> e.getState().equals(Employee.State.VOCATION));
System.out.println(b1);
//noneMatch:检查是否没有匹配所有元素
boolean b2 = emps.stream().noneMatch(e -> e.getState().equals(Employee.State.VOCATION));
System.out.println(b2);
//findFirst:返回第一个元素
Optional<Employee> first = emps.stream().sorted((e1, e2) -> -Double.compare(e1.getMoney(), e2.getMoney())).findFirst();
System.out.println(first.get());
Optional<Employee> first1 = emps.stream().sorted((e1, e2) -> -Double.compare(e1.getMoney(), e2.getMoney())).findAny();
System.out.println(first1.get());
//count:返回元素总个数
long count = emps.stream().count();
System.out.println(count);
//max:返回流中最大值
Optional<Employee> max = emps.stream().max((e1, e2) -> Double.compare(e1.getMoney(), e2.getMoney()));
System.out.println(max.get());
//max:返回流中最大值
Optional<Double> min = emps.stream().map(e -> e.getMoney()).min(Double::compare);
System.out.println(min.get());
}
public void test02(){
//reduce(T identity, BinaryOprator) / reduce(BinaryOprator) :可以将流中的元素反复结合起来,得到一个值
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(sum);
//map-reduce模式:map和reduce连用,Google用其进行网络搜索而得名
Optional<Double> reduce = emps.stream().map(e -> e.getMoney()).reduce((x, y) -> x + y);
reduce = emps.stream().map(Employee::getMoney).reduce(Double::sum);
System.out.println(reduce.get());
}
//收集
public void test03(){
//将员工的名字收集到list集合中,可以
List<String> collect = emps.stream().map(e -> e.getName()).collect(Collectors.toList());
collect.forEach(System.out::println);
//总数
Long sum = emps.stream().collect(Collectors.counting());
System.out.println(sum);
//平均值
Double avg = emps.stream().collect(Collectors.averagingDouble(Employee::getMoney));
System.out.println(avg);
//工资总和
Double sumS = emps.stream().collect(Collectors.summingDouble(Employee::getMoney));
System.out.println(sumS);
//最大值
Optional<Employee> max = emps.stream().collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getMoney(), e2.getMoney())));
System.out.println(max.get());
//最小值
Optional<Double> min = emps.stream().map(e -> e.getMoney()).collect(Collectors.minBy(Double::compare));
System.out.println(min.get());
}
//分组
public void test04(){
Map<Employee.State, List<Employee>> collect = emps.stream().collect(Collectors.groupingBy(Employee::getState));
System.out.println(collect);
}
}
收集:
方法 | 返回类型 | 作用 | 举例 |
---|---|---|---|
toList | List | 把流中元素收集到List | List emps= list.stream() .collect(Collectors.toList()); |
toSet | Set | 把流中元素收集到Set | List emps= list.stream() .collect(Collectors.toSet()); |
toCollection | Collection | 把流中元素收集到创建的集合 | Collectionemps=list.stream(). collect(Collectors.toCollection(ArrayList::new)); |
counting | Long | 计算流中元素的个数 | long count = list.stream().collect(Collectors.counting()); |
summingInt | Integer | 对流中元素的整数属性求和 | int total = list.stream().collect(Collectors.summingInt(Employee :: getAge)); |
averagingInt | Double | 计算流中元素Integer属性的平均值 | Double avg = emps.stream().collect(Collectors.averagingDouble(Employee::getMoney)); |
joining | String | 连接流中的每个字符串 | String str= list.stream().map(Employee::getName).collect(Collectors.joining()); |
maxBy,minBy | Optional | 选择最大最小值 | Optional max = list.stream().collect(Collectors.maxBy(comparingDouble(Employee::getMoney))) |