Lambda表达式在1.8版本中引入了新的语法规则,包括元素与“->”操作符,“->”操作符将Lambda分为两个部分:
- 左侧:指定了Lambda表达式需要传递的参数。
- 右侧:指定了Lambda体,也就是要写的一些代码功能。
基础用法:
public class lambda_01 {
public static void main(String[] args) {
// 建立int型数组
Integer[] arr = { 2, 5, 4, 7, 9, 6, 5, 6, 5, 8 };
// 将数组转化为集合
List<Integer> integers = Arrays.asList(arr);
// 排序
Collections.sort(integers, new Comparator<Integer>() {
@Override
// 覆写函数
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(integers);
// lambda 写法,应该是自动识别匿名内部类继承的接口
Collections.sort(integers, (o1, o2) -> o1 - o2);
System.out.println(integers);
}
}
回调函数 : 简单来说,就是写好功能,通过参数传递过去,让别人帮忙调用
public class lambda_02 {
public static void main(String[] args) {
int[] arr = { 1, 5, 8, 9, 6 };
// forEach(arr,new Array() {
// @Override
// public void m1(int i) {
// System.out.println(i);
// }
// });
forEach(arr, i -> System.out.println(i));
}
// 把接口当做参数,接口中只能有一个方法
public static void forEach(int[] arr, Array array) {
for (int i : arr) {
array.m1(i);
}
}
}
interface Array {
void m1(int i);
}
class A implements Array {
@Override
public void m1(int i) {
System.out.print(i);
}
}
函数对方法的调用:将方法传递给相应的函数接口
public class FunCall_01 {
public static void main(String[] args) {
Integer i1 = 10;
// 方法调用
String str = i1.toString();
System.out.println(str);
// lambda 写法
Supplier<String> supplier = () -> i1.toString();
System.out.println(supplier.get());
// 方法引用写法
Supplier<String> su1 = i1::toString;
System.out.println(su1.get());
// 类名::静态方法名
int max = Integer.max(10, 33);
BiFunction<Integer, Integer, Integer> bf = Integer::max;
System.out.println(bf.apply(10, 33));
// 类名::成员方法
BiPredicate<String, String> bp = String::equals;
System.out.println(bp.test("asd", "asd"));
// 数组
Integer[] is = new Integer[10];
Function<Integer, Integer[]> fun = Integer[]::new;
is = fun.apply(5);
System.out.println(is.length);
is[0] = 100;
BiFunction<Integer[], Integer, Integer> bc = (arr, index) -> arr[index];
System.out.println(bc.apply(is, 0));
}
}
什么是函数式接口
只包含一个抽象方法的接口,称为函数式接口。
可以通过Lambda表达式创建该接口的对象。(若Lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)。
可以在任何函数式接口上使用@FunctionalInterface注解,这样做可以检查它是否是一个函数式接口,同时javadoc也会包含一条声明,说明这个接口是一个函数式接口。
Lumbda表达式作为参数进行传递,为了将Lambda表达式作为参数传递,接受参数类型必须与Lambda表达式兼容的函数式接口的类型。
获取流:
public static void main(String[] args) {
// 1数组,通过stream类的of方法即可
String[] strings = { "a", "b", "C", "d" };
Stream<String> stream1 = Stream.of(strings);
// 2集合通过集合对象的stream方法即可
List<String> strings2 = Arrays.asList(strings);
Stream<String> stream2 = strings2.stream();
// 3通过Stream的generate方法创建无线流
// 该流无限大,建议使用limit限制条数
// 参数是一个Supplier接口,有一个get方法,无参,有返回值
// 返回的数据就会被放到这个无限流中,也就是,目前这个流中的数据都是1
Stream<Integer> stream3 = Stream.generate(() -> 1);
stream3.limit(10).forEach(x -> System.out.println(x));
// 4通过Stream.iterate方法创建无限流
// 第一个参数是起始值,第二个参数是一个UnaryOperator,是function的子类, 所以是有参有返回值
// x->x+2:等于步长为2,那么此时数据流中的内容为1,3,57911....
Stream<Integer> stream4 = Stream.iterate(1, x -> x + 2);
stream4.limit(5).forEach(x -> System.out.println(x));
// 5已有类的streamAPI
String string = " asdh";
IntStream is = string.chars();
is.forEach(x -> System.out.println(x));
}
中间阶段:
一个流只能有一个终止操作 如果不执行终止操作,中间操作也不会执行
public class Stream_02 {
public static void main(String[] args) {
Integer[] integers = { 6, 8, 4, 2, 5, 7, 5, 3, 5, 8 };
// 过滤
// 将数组转化为集合
List<Integer> list = Arrays.asList(integers);
// 将集合转化为流
Stream<Integer> stream = list.stream();
// filter :对元素进行筛选,不符合条件的就不要了
// collect返回的是集合类型 filter(x -> x == 5)括号内的函数是固定的
List<Integer> list1 = stream.filter(x -> x == 5).collect(
Collectors.toList());
System.out.print(list1);
/**
* distinct 去除重复
*/
stream = list.stream();
List<Integer> result = stream.distinct().collect(Collectors.toList());
System.out.println(result);
/**
* map
*/
List<Integer> says = Arrays.asList(2000, 1000, 2800, 6666, 8888);
Stream<Integer> stream1 = says.stream();
// 所有人涨薪百分之十
says = stream1.map(x -> x + x / 100 * 10).collect(Collectors.toList());
System.out.println(says);
/**
* sorted 排序
*/
stream1 = says.stream();
// 默认是升序 [1100, 2200, 3080, 7326, 9768]
// says = stream1.sorted().collect(Collectors.toList());
// 降序 [9768, 7326, 3080, 2200, 1100]
says = stream1.sorted((x, y) -> y - x).collect(Collectors.toList());
System.out.println(says);
}
}
终止:
终止操作又称为动作算子
forEach循环遍历
collect收集器
计算相关min, max, count, avrage .
匹配相关anyMatch, al IMatch. . .
public static void main(String[] args) {
List<String> strings = Arrays.asList("a", "s", "r", "q", "t");
// forEach
Stream<String> stream = strings.stream();
stream.forEach(x -> System.out.print(x));
System.out.println();
// 统计
stream = strings.stream();
// 统计元素个数,一般需要和中间操作结合使用,否则不如集合size方法
long count = stream.count();
System.out.print(count);
System.out.println();
// 统计有多少a
stream = strings.stream();
// 统计元素个数,一般需要和中间操作结合使用,否则不如集合size方法,count返回值为个数
count = stream.filter(x -> x == "a").count();
System.out.print(count);
System.out.println();
// 最大值 max 最小值 min
List<Integer> list = Arrays.asList(1, 4, 6, 9, 7, 5, 3);
Stream<Integer> stream2 = list.stream();
int max = stream2.max((x, y) -> x - y).get();
System.out.print(max);
System.out.println();
// 匹配相关 anyMatch 匹配数据 比如是否包含
Stream<Integer> stream1 = list.stream();
boolean result = stream1.anyMatch(x -> x == 3);
System.out.print(result);
System.out.println();
// 比如 所有学生中,判断是否有19岁的
List<Student> students = new ArrayList<Student>();
students.add(new Student("张三", 20));
students.add(new Student("李四", 21));
students.add(new Student("王五", 20));
students.add(new Student("赵六", 29));
// 判断
Stream<Student> stream3 = students.stream();
boolean r = stream3.anyMatch(x -> x.age == 29);
System.out.print(r);
}
}
class Student {
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}