目录
1.lambd表达式
- lamada表达式函数必须保证所传递函数是只有一个抽象方法的接口类.
- 相当于匿名内部类(一个一次性的单一抽象方法接口类)的升级版,在箭头函数调用lamuda表达式时,必须与抽象方法一一对应,否则调用失败报错
- 单句不想返回,则加{}不用加return,
Integer [] arr = {1,5,4,2,8,3,4,9};
List<Integer> list = Arrays.asList(arr);
//匿名内部类实现排序(降序)
list.sort(new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
//lambda表达式实现排序(升序)
list.sort((o1,o2)->o1-o2);
for (Integer integer : list) {
System.out.print(integer +" ");
}
- 函数式接口,给lambda表达式操作空间只留一个抽象方法,可以有其他实现的方法, (就是一个像函数的接口类)
有参的函数式接口(附三种调用方式)
无参的直接写call(()->System.out.println(“lambda表达式”));
public class _02_FunInterface {
public static void main(String[] args) {
String str = "有参函数式接口调用";
// 1 匿名内部类
call(new MyFunctionInter2(){
@Override
public void printMessage(String str) {
System.out.println(str);
}
}, str);
// 2 lambda
call(s -> System.out.println(s), str);
// 3 创建函数对象
MyFunctionInter2 inter2 = s -> System.out.println(s);
call(inter2, str);
}
// str为 printMessage方法的参数
public static void call(MyFunctionInter2 func,String str) {
// 调用func对象 的printMessage方法 并传入 str
func.printMessage(str);
}
}
@FunctionalInterface
interface MyFunctionInter2 {
void printMessage(String str);
}
2.supplier
- 泛型中可以规定任意类型
- 表示供应商,所以有返回值,可以获取数据
// 实现接口函数
public static Integer getResult(Supplier<Integer> supplier) {
return supplier.get();
}
// 匿名内部类实现
int i = getResult(new Supplier<Integer>() {
@Override
public Integer get() {
return 2;
}
});
System.out.println(i);
// lambda表达式实现
i = getResult(() -> 7);
System.out.println(i);
3.Consumer
- 表示消费者接口,所以不需要返回值
//前一个参数即为accept的实现方法体,后一个参数是传入是accept要传入的参数
call((s)->System.err.println(s),str);
}
public static void call(Consumer<String> c,String msg){
c.accept(msg);
}
4.Function
- Function<T,R> 实现方法中传入T类型,返回R类型
R apply(T t) 方法
public static void main(String[] args) {
//写的是apply的参数和返回值
int num = convertType(x->(int)x, 'a');
System.out.println(num);
}
// 把字符串转换为数字
public static Integer convertType(Function<Character,Integer> function, Character ch) {
int i = function.apply(ch);
return i;
}
5.Predicate
-
Predicate 接口 断言接口,就是做一些判断
-
booean test(T) 用于做校验比较操作
public static void main(String[] args) {
String message = "ok1";
boolean result = call(msg->msg.equals("ok"),message);
System.out.println(result);
}
//booean test(T) 用于做校验比较操作
public static boolean call(Predicate<String> predicate, String message) {
return predicate.test(message);
}
6.方法引用简写
-
Lambda表达式的另一种表示形式,提高复用率和灵活性
-
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
-
方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
-
要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!
-
格式:使用操作符“::” 将类(或对象) 与方法名分隔开来。
-
如下三种主要使用情况:
对象::实例方法名
类::静态方法名
类::实例方法名
对象::实例方法名
public static void main(String[] args) {
Integer i = new Integer(123);
//lambda表达式
Supplier<Integer> supplier = ()->i.hashCode();
System.out.println(supplier.get());
//对象的引用::实例方法
Supplier<Integer> supplier1 = i::hashCode;
System.out.println(supplier1.get());
call(()->i.hashCode());
call(i::hashCode);
}
public static Integer call(Supplier<Integer> sup){
return sup.get();
}
类::静态方法名
int i = 123;
//lambda表达式写法
Function<Integer,String> fun = x -> Integer.toBinaryString(i);
System.out.println(fun.apply(i));
//类名::静态方法名()省略了参数,因为调用apply时还会调用
Function<Integer,String> fun1 = Integer::toBinaryString;
System.out.println(fun1.apply(i));
类::实例方法名
//lambda表达式
BiPredicate<String,String> bi = (x,y)->x.equals(y);
System.out.println(bi.test("oak","ok"));
//类名::实例方法
BiPredicate<String,String> bi1 = String::equals;
System.out.println(bi1.test("ock","ock"));
7.构造方法简写
构造方法
//无参构造器
Supplier<Student> sup11 = () -> new Student();
System.out.println(sup11.get());
Supplier<Student> sup12 = Student::new;
System.out.println(sup12.get());
//有参构造器
Supplier<Student> sup21 = () -> new Student("王老菊");
System.out.println(sup21.get().getName());
//apply()的<参数,返回值>
Function<String,Student> sup22 = Student::new;
System.out.println(sup22.apply("王老菊").getName());
8.数组声明简写
数组声明简写
// 数组引用写法,只能动态声明,不能静态声明
Function<Integer, Integer[]> fun1 = Integer[]::new;
Integer[] arr1 = fun1.apply(2);
System.out.println(arr1.length);
9.StreamAPI
- 简言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
就是用来处理集合、数组的API,集合讲的是数据,而流是计算
注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
9.1 创建流
// 1 通过数组 Stream.of
String[] strings = { "a", "b", "c", "d" };
Stream<String> stream1 = Stream.of(strings);
// 2 通过集合
List<String> strings2 = Arrays.asList(strings);
Stream<String> stream2 = strings2.stream();
// 3 通过Stream.generate 方法来创建
// 这是一个无限流,无限大,通过这种方式创建的流,在操作的时候,最好使用limit进行最大数量限制
// generate的参数是 Supplier 只有一个get方法,是无参有返回值的
// get方法的返回值,作为整个集合中的数据,下面这个等于都赋值为1
Stream<Integer> generate = Stream.generate(() -> 1);
// 可以通过limit限制最多元素个数
generate.limit(5).forEach(x -> System.out.println(x));
// 4 通过Stream.iterate 方法来创建
// 这是一个无限流,无限大,通过这种方式创建的流,在操作的时候,最好使用limit进行最大数量限制
// 第一个参数是起始值,第二个参数是UnaryOperator 继承了Function 所以 有参有返回值
// 1 就是起始值, x+2 就是步长,类似于一个死循环,起始值是1,步长 是2,终止条件是true
Stream<Integer> iterate = Stream.iterate(1, x->x+2);
iterate.limit(5).forEach(x->System.out.println(x));
// 5 已有类的Stream源生成API
String str = "abc";
IntStream chars = str.chars();
chars.forEach(x->System.out.println(x));
9.2 流的中间操作(转换算子)
stream.(转换算子).(动作算子)
- filter : 对元素进行过滤,不符合条件的,就不要了
- distinct : 去掉重复
- skip : 跳过多少个元素
- limit : 取一个集合中的前几条数据
- map : 可以理解为是在遍历集合的过程中,对元素进行操作. 比如进行判断,集合元素是否大于4 ,返回值为boolean类型,或者对集合元素进行更改,比如每个元素都自身+1
- flatMap : 解决一个字符串数组,返回单一的字符串使用flatMap
public static void main(String[] args) {
String[] arr = { "a", "b", "c", "a" };
List<String> strings = Arrays.asList(arr);
// 创建流对象
Stream<String> stream = strings.stream();
// filter:对元素进行过滤(参数为predicate(参数<T>返回值boolean))
List<String> value = stream.filter(x -> x.equals("a")).collect(
Collectors.toList());
System.out.println(value);
// 需要重新生成一个stream,否则报错,不能使用同一个stream
stream = strings.stream();
value = stream.skip(1).collect(Collectors.toList());
System.out.println(value);
// map,在遍历过程中,对元素进行操作,返回Boolean类型
stream = strings.stream();
//在元素尾部添加字符串
List value1 = stream.map(x -> x+"xxx").collect(
Collectors.toList());
System.out.println(value1);
//distinct去重
stream = strings.stream();
value = stream.distinct().collect(Collectors.toList());
System.out.println(value);
//limit(n) :取集合中前n条数据
stream = strings.stream();
value = stream.limit(2).collect(Collectors.toList());
System.out.println(value);
//flatMap : 合并两段数组
String[] arr1 = {"abc","abc"};
strings = Arrays.asList(arr1);
stream = strings.stream();
value = stream.map(x->x.split("")).flatMap(array->Arrays.stream(array)).collect(Collectors.toList());
System.out.println(value);
}
9.3 流的终止操作(动作算子)
stream.(转换算子).(动作算子)
- forEach : 循环
- 计算 : min,max,count,average
- 匹配 :anyMatch,allMatch,noneMatch,findFirst,findAny
- 汇聚 : reduce
- 收集器 : collect
String[] arr = { "a", "b", "c" };
List<String> strings = Arrays.asList(arr);
Stream<String> stream = strings.stream();
// 测试forEach
stream.filter(x -> x.equals("a")).forEach(x -> System.out.println(x));
// 测试 count
stream = strings.stream();
long count = stream.count();
System.out.println(count);
//统计 有几个a
stream = strings.stream();
count = stream.filter(x -> x.equals("a")).count();
System.out.println(count);
// collect收集器
// 把结果收集,并组织成集合
stream = strings.stream();
List<String> list = stream.map(x -> x + "==").collect(
Collectors.toList());
System.out.println(list);