一. lambda表达式的基本介绍
Lambda表达式的语法
基本语法:
(parameter) -> {expression}
或
(parameters) ->{ statements; }
或者
(parameters1,parameters1, ......) ->{ statements; }
当然有时()与{}都可以省去不写。
下面简单介绍一下Java lambda表达式的几个例子:
// 1. 不需要参数,返回值为 3
() -> 3
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
我个人还是比较推荐新入门的写全lambda表达式即()-> {} 的形式。
Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。
lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。
Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及 java.util.stream 包。
二.Stream流的基本介绍
Stream是对集合的包装,通常和lambda一起使用。 使用lambdas可以支持许多操作,如 map, filter, limit, sorted, count, min, max, sum, collect 等等。 同样,Stream使用懒运算,他们并不会真正地读取所有数据,遇到像getFirst() 这样的方法就会结束链式语法。
在接下来的例子中,我们将探索lambda和stream能做什么。 我们创建了一个User类并使用这个类来添加一些数据到list中,将用于进一步流操作。 User 只是一个简单的POJO类:
import lombok.Data;
// 这里我导入了lombok 包 使用注解 @Data自动生成 get,set,toString等方法
@Data
class User{
Integer id;
String name;
Integer age;
public User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
下面我简单演示了几种Stream+lanbda的操作,具体介绍了一下map, filter, sorted的用法
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
User u1 = new User(1,"a",21);
User u2 = new User(2,"b",22);
User u3 = new User(3,"c",23);
User u4 = new User(4,"d",24);
User u5 = new User(5,"e",25);
// 集合用来存储数据
List<User> list = Arrays.asList(u1,u2,u3,u4,u5);
// stream 流用来计算
// 过滤id为偶数的用户,打印输出
list.stream().filter((user)->{return user.getId()%2==0;})
.forEach(user -> {
System.out.println(user);
});
// 过滤年龄大于等于23岁的用户打印输出
System.out.println("===================");
list.stream().filter(user -> {return user.getAge()>=23;}).forEach(user -> {
System.out.println(user);
});
System.out.println("============");
// 将用户名转为大写返回并输出
list.stream().map(user -> {return user.getName().toUpperCase();}).forEach(user->{
System.out.println(user);
});
System.out.println("==============");
list.stream().sorted((uu1,uu2)->{return uu2.getAge().compareTo(uu1.getAge());})
.forEach(user -> System.out.println(user));
}
}
Streams 还可以是并行的(parallel)。 示例如下:
long sum = LongStream
.rangeClosed(0L, 10_0000_0000L)
.parallel()
.reduce(0, Long::sum);
其中rangeClosed为长整型流的范围,parallel为并行操作,reduce(0,Long::sum)为对流中的数据进行求和
简单来讲就是结果就等价于下面的求和
for (Long i = 1l; i <= 10_0000_0000; i++) {
sum+=i;
}
但如果有兴趣你可以比较一下两种求和方式的具体执行时间,使用并行方式效率提高了可以说几十倍不止
其他的Stream流方法这里不多做介绍可以自行测试。
三.四大函数式接口的基本介绍
那什么时候可以用 lambda 表达式呢,可以说凡是实现函数式接口的地方就可以用 lambda 表达式。
而函数式接口主要分为以下四种Function,Predicate,Consumer,Supplier
@FunctionalInterface public interface Function<T, R>{ R apply(T t); } @FunctionalInterface public interface Predicate<T> { boolean test(T t); } @FunctionalInterface public interface Consumer<T> { void accept(T t); } @FunctionalInterface public interface Supplier<T> { T get(); }
而他们的主要区别也在与有无参数,以及有无返回值,以下是具体举例说明使用方法(结合lambda)
Function<String, String> function = (str)->{return str;};
System.out.println(function.apply("hello,world"));
Predicate<String> predicate = (str)->{return str.isEmpty();};
System.out.println(predicate.test("wjjjj"));
Consumer<String> consumer = (string)->{
System.out.println(string);
};
consumer.accept("come on");
Supplier<Integer> integerSupplier = () -> {
return 1024;
};
System.out.println(integerSupplier.get());