1.Lambda
1.1概述
Lambda表达式是一种没有名字的函数,也可称为闭包,是Java 8 发布的最重要新特性。
本质上是一段匿名内部类,也可以是一段可以传递的代码。
还有叫箭头函数的
1.2优点
是匿名内部类的简写方式,使代码更加简洁
1.3和匿名内部类对比
String[] strs = {"12","2","123","1"};
// 转换为list
List<String> strings = Arrays.asList(strs);
// 匿名内部类
Collections.sort(strings,new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
Integer i1 = Integer.valueOf(o1);
Integer i2 = Integer.valueOf(o2);
// 升序
return i1 - i2;
}
});
// 箭头函数
Collections.sort(strings,(s1,s2)->{
// 多条语句
Integer i1 = Integer.valueOf(s1);
Integer i2 = Integer.valueOf(s2);
// 降序
return i2 - i1;
});
1.4语法结构
(参数,参数,参数...) -> {方法体}
1 无参和多参,小括号必须写
2 只有一个参数的时候,小括号可以不写
3 如果只有一条语句,大括号也可以不写,并且语句结尾不需要 分号
4 如果只有一条语句,并且也是返回值语句的话,return 也要省略
5 如果是多条语句,必须加{},就是正常编码,该写分号写分号,该写return就写return
1.5案例
public static void main(String[] args) {
String[] strs = {"12","2","123","1"};
// 转换为list
List<String> strings = Arrays.asList(strs);
// 匿名内部类
Collections.sort(strings,new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
Integer i1 = Integer.valueOf(o1);
Integer i2 = Integer.valueOf(o2);
// 升序
return i1 - i2;
}
});
// 箭头函数
Collections.sort(strings,(s1,s2)->{
// 多条语句
Integer i1 = Integer.valueOf(s1);
Integer i2 = Integer.valueOf(s2);
// 降序
return i2 - i1;
});
System.out.println(strings);
}
}
public static void main(String[] args) {
Integer[] is = { 1, 4, 5, 2, 3, 7 };
List<Integer> list = Arrays.asList(is);
// 1.8之前写法
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
// lambda写法
Collections.sort(list, (x, y) -> x - y);
System.out.println(list);
}
}
public static void main(String[] args) {
Integer[] is = { 1, 4, 5, 2, 3, 7 };
List<Integer> list = Arrays.asList(is);
// 1.8之前 常规写法
for (Integer integer : list) {
System.out.println(integer);
}
System.out.println("----");
// 1.8 匿名内部类写法
list.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer t) {
System.out.println(t);
}
});
System.out.println("----");
// 1.8 lambda写法
list.forEach(x -> System.out.println(x));
}
}
2.函数式接口
2.1概述
英文称为Functional Interface
其本质是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
核心目标是为了给Lambda表达式的使用提供更好的支持,进一步达到函数式编程的目标,可通过运用函数式编程极大地提高编程效率。
其可以被隐式转换为 lambda 表达式。
2.2特点
函数式接口是仅制定一个抽象方法的接口
可以包含一个或多个静态或默认方法
专用注解即@FunctionalInterface 检查它是否是一个函数式接口,也可不添加该注解
如果有两个或以上 抽象方法,就不能当成函数式接口去使用,也不能添加@FunctionalInterface这个注解
如果只有一个抽象方法,那么@FunctionalInterface注解 加不加 都可以当做函数式接口去使用
2.3自定义
public static void main(String[] args) {
// 子实现类的写法
Test test = new Test();
m1(test);
// 匿名内部类
m1(new MyFunction() {
@Override
public void print() {
System.out.println("匿名内部类写法");
}
});
// lambda写法
m1(() -> System.out.println("lambda表达式写法"));
}
public static void m1(MyFunction function) {
function.print();
}
}
// 可以加也可以不加,
// 函数式接口中,只允许出现一个抽象方法,和N个非抽象方法
@FunctionalInterface
interface MyFunction {
public void print();
}
class Test implements MyFunction {
@Override
public void print() {
System.out.println("我是Test实现类");
}
}
2.4JDK自带的函数式接口
Supplier : 表示供应商,有个get方法,无参,有返回值,一般用于获取数据
Consumer : 表示消费者,accept,有参,无返回值
Function ,函数操作, apply , 有参也有返回值
Predicate 断言,用于做判断校验操作,test,需要传入参数并返回boolean类型
3.方法、构造器、数组
3.1概述
Lambda表达式的另外一种形式
3.2方法引用
/**
* 对象引用 :: 成员方法名
*
*
*/
public class FunCall_01 {
public static void main(String[] args) {
Integer i1 = 12;
Supplier<String> supplier = i1::toString;
System.out.println(supplier.get());
System.out.println(i1.toString());
}
}
**
* 类名 :: 静态方法名
*
*/
public class FunCall_02 {
public static void main(String[] args) {
String string = "123";
Function<String, Integer> function = Integer::parseInt;
int value = function.apply(string);
System.out.println(value);
}
}
/**
* 类名 :: 成员方法名
*
*/
public class FunCall_03 {
public static void main(String[] args) {
BiPredicate<String, String> predicate = String::equals;
System.out.println(predicate.test("a", new String("a")));
}
}
3.3构造器使用
public static void main(String[] args) {
// 无参构造
Supplier<Object> s1 = Object::new;
System.out.println(s1.get());
// 有参构造
Function<String, String> f1 = String::new;
System.out.println(f1.apply("zxc"));
}
}
3.4数组引用
public static void main(String[] args) {
// 泛型第一个是长度,第二个是返回值
Function<Integer, Integer[]> fun = Integer[]::new;
Integer[] arr = fun.apply(4);
for (Integer integer : arr) {
System.out.println(integer);
}
}
}
4.Stream API
4.1概述
数据渠道、管道,用于操作数据源(集合、数组等)所生成的元素序列。
集合讲的是数据,流讲的是计算
即一组用来处理数组,集合的API。
4.2特点
Stream 不是数据结构,没有内部存储,自己不会存储元素。
Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
不支持索引访问。
延迟计算
支持并行
很容易生成数据或集合
支持过滤,查找,转换,汇总,聚合等操作。
4.3应用场景
流式计算处理,需要延迟计算、更方便的并行计算
更灵活、简洁的集合处理方式场景
4.4创建流的五种方式
public static void main(String[] args) {
// 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来创建
// 创建一个无限流,里面全是1,并且通过limit 限制条数是5条
Stream<Integer> generate = Stream.generate(()->1);
generate.limit(5).forEach(x -> System.out.println(x));
// 4 通过Stream.iterate来创建
// 创建一个无限流,里面的数据有序,从2开始步长为3
Stream<Integer> iterate = Stream.iterate(2, x->x+3);
iterate.limit(5).forEach(x -> System.out.println(x));
// 5 通过已有API
String string = "abc";
IntStream chars = string.chars();
chars.forEach(x->System.out.println(x));
}
}
4.5转换算子
4.5.1概述
转换算子,又称为 中间操作,所有的转换算子得到的都是一个新的流,所以一般用于链式调用
* 常用的转换算子
* limit : 取集合中的前几条数据
* filter : 对元素进行过滤筛选,不符合条件的就不要了
* distinct : 去除重复
* skip : 跳过
* map : 更改数据
* sorted : 排序
* 注意 : 只有转换算子,是不执行的,必须执行动作才会真正执行
4.5.3常用方法
public static void main(String[] args) {
List<String> strings = Arrays.asList("a", "b", "c", "a");
// 只要a
Stream<String> stream = strings.stream();
// collect 动作算子,把流中的数据转换为集合
// filter 不符合条件的就不要了,返回false就是不要,true就是要
List<String> value = stream.filter(x -> x.equals("a")).collect(
Collectors.toList());
System.out.println(value);
// 不要偶数
List<Integer> integers = Arrays.asList(1, 3, 5, 6, 8, 9, 11, 144, 25,
257);
Stream<Integer> stream1 = integers.stream();
List<Integer> vaIue2 = stream1.filter(x -> x % 2 == 1).collect(
Collectors.toList());
System.out.println(vaIue2);
// skip : 跳过元素
stream1 = integers.stream();
vaIue2 = stream1.skip(2).collect(Collectors.toList());
System.out.println(vaIue2);
// distinct : 去重
stream = strings.stream();
value = stream.distinct().collect(Collectors.toList());
System.out.println(value);
// map : 遍历过程中对元素进行操作,比如涨薪
List<Double> sal = Arrays.asList(1152.2,2000.5,8888.8);
Stream<Double> salStream = sal.stream();
List<Double> newSal = salStream.map(x->x*10).collect(Collectors.toList());
System.out.println(newSal);
// limit 前几条,比如查看前两名
salStream = sal.stream();
// sorted 进行排序 y-x 是降序 , x-y 是升序
newSal = salStream.sorted((x,y)->{
if(y>x){
return 1;
}else if (y == x) {
return 0;
}else{
return -1;
}
}).limit(2).collect(Collectors.toList());
System.out.println(newSal);
}
}
4.6动作算子
public static void main(String[] args) {
List<String> strings = Arrays.asList("a", "b", "c", "a");
// 只要a
Stream<String> stream = strings.stream();
// collect 动作算子,把流中的数据转换为集合
// filter 不符合条件的就不要了,返回false就是不要,true就是要
List<String> value = stream.filter(x -> x.equals("a")).collect(
Collectors.toList());
System.out.println(value);
// 不要偶数
List<Integer> integers = Arrays.asList(1, 3, 5, 6, 8, 9, 11, 144, 25,
257);
Stream<Integer> stream1 = integers.stream();
List<Integer> vaIue2 = stream1.filter(x -> x % 2 == 1).collect(
Collectors.toList());
System.out.println(vaIue2);
// skip : 跳过元素
stream1 = integers.stream();
vaIue2 = stream1.skip(2).collect(Collectors.toList());
System.out.println(vaIue2);
// distinct : 去重
stream = strings.stream();
value = stream.distinct().collect(Collectors.toList());
System.out.println(value);
// map : 遍历过程中对元素进行操作,比如涨薪
List<Double> sal = Arrays.asList(1152.2,2000.5,8888.8);
Stream<Double> salStream = sal.stream();
List<Double> newSal = salStream.map(x->x*10).collect(Collectors.toList());
System.out.println(newSal);
// limit 前几条,比如查看前两名
salStream = sal.stream();
// sorted 进行排序 y-x 是降序 , x-y 是升序
newSal = salStream.sorted((x,y)->{
if(y>x){
return 1;
}else if (y == x) {
return 0;
}else{
return -1;
}
}).limit(2).collect(Collectors.toList());
System.out.println(newSal);
}
}