在日常工作中使用lambda表达可以较少与业务代码无关的代码,提高代码的可读性及使用很少的代码即可完成相关功能的代码编写。
数据准备
在使用这些方法之前先准备一些测试数据。测试数据如下:
新建的student的javabean如下:
public class Student {
private String name;
private int age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
在main方法中添加新建一个List的模拟数据.
List<Student> students = new ArrayList<>();
students.add(new Student("user1", 18));
students.add(new Student("user2", 26));
students.add(new Student("user3", 30));
students.add(new Student("user4", 10));
students.add(new Student("user4", 10));
常用方法
- map方法
map方法可以实现流的转换,如我们原先的流为R对象,通过map方法我们将流中的R对象转为T .map方法的源码如下:
// 接收一个Function的函数式接口,
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
其中Function的源码如下:
接收T,R两个类型的参数,最后返回R类型的参数.
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
使用map的demo:
List<Integer> list = students.stream().map(x -> x.getAge()).
collect(Collectors.toList());
list.forEach(x -> System.out.println(x)); // 18,26,30,10,10
和map功能相类似的有mapInt和mapToLong或者mapToDouble,他们都返回特定的返回值类型.
List<Integer> list = students.stream().mapToInt(x -> x.getAge())
// 必须有mapToObj,因为mapToInt已经是返回一个IntStream,已经明确返回的类型
// 已经没有泛型了明确了int,而Collectors.toList,需要泛型类型的流,故
// 必须使用mapToObj方法返回有泛型的流
.mapToObj(x -> x).
collect(Collectors.toList());
list.forEach(x -> System.out.println(x)); // 18,26,30,10,10
- distinct方法
distinct方法具有去重的功能,使用demo如下:
List<Student> list = students.stream().distinct().
collect(Collectors.toList());
list.forEach(x -> System.out.println(x));
- filter方法
filter方法具有过滤的功能,类型与我们if中的条件一样只有符合了条件才能被保留下来,不满足则进行过滤。
filter源码如下:
// 传入一个Predicate的函数式接口
Stream<T> filter(Predicate<? super T> predicate);
// 而Predicate根据入参的T返回boolean类型
filter使用demo如下:
List<Student> list = students.stream().filter(x -> x.getAge() > 25).
collect(Collectors.toList());
list.forEach(x -> System.out.println(x));
- flapMap方法
flapMap方法也可以做一些流的转换,只是和map不同的是它Function明确了返回值类型。
List<Student> students = new ArrayList<>();
students.add(new Student("user1", 18,Arrays.asList(100,98,98)));
students.add(new Student("user2", 26,Arrays.asList(100,98,98)));
students.add(new Student("user3", 30,Arrays.asList(100,98,98)));
students.add(new Student("user4", 10, Arrays.asList(100,98,98)));
students.add(new Student("user4", 10,Arrays.asList(100,98,98)));
List<Integer> list = students.stream().flatMap(x -> x.getCourses().stream()).
collect(Collectors.toList());
list.forEach(x -> System.out.println(x));
- sorted方法
sorted方法提供了排序功能,也可以实现自定义排序。
List<Integer> list = students.stream().map(Student::getAge)
.sorted().
collect(Collectors.toList());
list.forEach(x -> System.out.println(x));
- limit方法
limit方法作用限制输出值的个数,入参是限制的大小,demo如下:
List<Student> list = students.stream().limit(2).
collect(Collectors.toList());
list.forEach(x -> System.out.println(x));
- reduce方法
reduce方法允许我们在循环中,对一些值进行一些叠加操作,demo如下:
Integer sum= students.stream().map(Student::getAge).
reduce((x,y) -> x+y).orElse(0);
System.out.println(sum);
- peek方法
peek方法是没有任何返回值滴,但是可以做一些日志的打印功能,demo如下:
List<Student> list = students.
stream().peek(x -> System.out.println(x))
.collect(Collectors.toList());
- findFirst方法
findFirst方法去除第一个值,和filter 方法一起使用可以有更不错的效果,demo如下:
int list = students.
stream().filter(x -> x.getAge() > 28).findFirst().get().getAge();
System.out.println(list);
以上是lambda表达式常用的方法。