一、Lambda表达式
- 本质:是一个匿名的接口
- 前提条件 必须是函数型接口 接口中只能有一个抽象方法 可以有其它的方法
- 作用:简化匿名内部类的写法
- 语法: (参数) ->{方法体}
- 解释:
(参数)==>接口中抽象方法的参数
-> 指向方法体
{} 执行方法的操作 - Lambda 表达式简化的方式
A. 如果方法只有一个参数 小括号与数据类型可以省略
B. 如果方法体 只有一句话 这句话是retrun 就可以省略大括号 与retrun与分号
C. 如果方法没有返回值 只有一句方法体 可以省略大括号与分号
代码示例:
public class Test01 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}).start();
//lambda 表达式简化
new Thread(()->System.out.println(Thread.currentThread().getName())).start();
}
}
二、jdk8与jdk9接口的新特性(了解)
2.1 简介
- 概念:在jdk1.8之后 接口中不仅可以有抽象方法 还可以有其它的方法
- 增加方法:
jdk8:默认的方法与静态的方法
jdk9: 私有的方法 - 影响:
接口中可以有其它的成员方法 接口与抽象类的差距缩小 接口多继承 多实现 使用接口是趋势
2. 默认的方法
- 概念:使用default进行修饰的方法就是默认的方法
- 语法:
default 方法返回值类型 方法的名称(参数列表) {
方法体;
retrun 返回值;
} - 特点:
A.接口中的默认方法只能通过实例化实例化来进行调用
B.接口中的默认方法 实现类可以不重写
C.实现类的其它方法可以调用接口中的默认方法,调用的语法是 接口的名称.super.方法的名称()
三、 jdk8 四个函数型接口(了解)
3.1 Supplier 供给型接口
方法的名称 | 方法的描述 |
---|---|
T get() | 得到一个结果 |
代码
import java.util.function.Supplier;
public class Test01 {
public static void main(String[] args) {
showInfo(()->{
return "666";
});
System.out.println(showInfo(() -> "666"));
}
public static String showInfo(Supplier<String> sup){
return sup.get();
}
}
代码 -使用供给型的接口求出数组中最大值
import java.util.Arrays;
import java.util.function.Supplier;
public class Test02 {
public static void main(String[] args) {
getMax(()->{
//定义数组
int [] arrays={20,9,3,43,32};
/* int max=arrays[0];
for (int i=0;i<arrays.length;i++) {
if (arrays[i] >max) {
max = arrays[i];
}
}*/
Arrays.sort(arrays);
int max = arrays[arrays.length-1];
return max;
});
}
public static Integer getMax(Supplier<Integer> supp) {
return supp.get();
}
}
3.2 Consumer 消费型接口
方法的名称 | 方法的描述 |
---|---|
void accept(T t) | 在给定的参数上执行此操作(消费的方法) |
default Consumer andThen(Consumer<? super T> after) | 可以连接多个消费型接口(可以进行多次消费) |
代码-使用消费型接口 获取字符的第一个字符
import java.util.function.Consumer;
public class Test01 {
public static void main(String[] args) {
/* showInfo("阿豪",(String s) ->{
System.out.println(s.substring(0,1));
});*/
showInfo("阿豪",s-> System.out.println(s.substring(0,1)));
}
public static void showInfo(String s,Consumer<String> con){
con.accept(s);
}
}
代码-对一个字符串进行两个消费 第一次消费转换为大写 第二次 消费转换为小写
import java.util.function.Consumer;
public class Test02 {
public static void main(String[] args) {
show("abcDEF",(String s)->{
System.out.println(s.toLowerCase()); //转换为小写
},(String n)->{
System.out.println(n.toUpperCase()); //转换为大写
});
}
public static void show(String s, Consumer<String> con1,Consumer<String> con2){
con1.andThen(con2).accept(s);
}
}
代码-对字符串数组进行消费 String [] array={“迪丽热巴:20”,“古力娜扎:22”,“马尔扎哈:30”}
在控制台输出 姓名:迪丽热巴 年龄:20 , 姓名:古力娜扎 年龄:22
import java.util.function.Consumer;
public class Test03 {
public static void main(String[] args) {
String [] arrays={"迪丽热巴:28","古力娜扎:32","马尔扎哈:40"};
showInfo(arrays,(String s) ->{
System.out.print("姓名:"+s.split(":")[0]+",");
},(String n)->{
System.out.print("年龄:"+n.split(":")[1]);
System.out.println(" ");
});
}
public static void showInfo(String []arrays, Consumer<String> co1,Consumer<String> co2){
for (String s :arrays) {
co1.andThen(co2).accept(s);
}
}
}
3.3 Predicate 断言型接口 用于判断
方法的名称 | 方法的描述 |
---|---|
boolean test(T t) | 用于来做判断 |
default Predicate and(Predicate<? super T> other) | (并且 &&) |
default Predicate or(Predicate<? super T> other) | (或者 ||) |
default Predicate negate() | (非 !) |
代码
import java.util.function.Predicate;
public class Test01 {
public static void main(String[] args) {
boolean flag = isFlag("准备吃排骨猪脚饭",(String s)->{
return s.length() >5;
});
System.out.println(flag);
boolean f = isFlag("是广州最亮的仔,名字叫叼毛",(String s)->{
return s.length()>5;
},(String n)->{
return n.contains("靓仔");
});
System.out.println(f);
System.out.println(showInfo("表哥要结婚", (String s) -> {
return s.contains("表哥");
}));
}
/**
* 判断字符串的长度>5
* @param s
* @param pre
* @return
*/
public static boolean isFlag(String s, Predicate<String> pre){
return pre.test(s);
}
public static boolean isFlag(String s,Predicate<String> pre1,Predicate<String> pre2){
//return pre1.and(pre2).test(s);
return pre1.or(pre2).test(s);
//return pre1.negate().test(s);
}
public static boolean showInfo(String s,Predicate<String> p){
return p.negate().test(s);
}
}
代码- 定义一个数组 String[] arrays={“迪丽热巴”,“古力娜扎”,“杨幂”,“杨颖”,“黄天良”,“雷凌”,“杨迪哈哈”}
使用断言型接口将数组中包含迪 并且长度为4 的元素存入到集合
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class Test02 {
public static void main(String[] args) {
String[] arrays={"迪丽热巴","古力娜扎","杨幂","杨颖","杨迪哈哈"};
List<String> list = showInfo(arrays,(String s)->{
return s.length() ==4;
},(String n)->{
return n.contains("迪");
});
System.out.println(list);
}
public static List<String> showInfo(String [] arrays, Predicate<String>pre1,Predicate<String> pre2){
//实例化集合
List<String> li = new ArrayList<>();
//使用循环遍历数组
for (String s :arrays) {
if (pre1.and(pre2).test(s)) {
li.add(s);
}
}
return li;
}
}
3.4 Function 函数型接口 转换型
方法的名称 | 方法的描述 |
---|---|
default Function<T,V> andThen(Function<? super R,? extends V> after) | 连接多个函数型接口 |
R apply(T t) ==>将T类型转换为R类型 | 用于来进行准换 |
代码-使用函数型接口 将String类型转换为int类型
import java.util.function.Function;
public class Test01 {
public static void main(String[] args) {
System.out.println(showInfo("123", (String s) -> {
return Integer.parseInt(s);
}));
System.out.println(show("123", (String s) -> {
return Integer.parseInt(s);
}, (Integer n) -> {
return n + "";
}));
}
public static Integer showInfo(String s, Function<String,Integer> fun) {
return fun.apply(s);
}
public static String show(String s,Function<String,Integer>fun1,Function<Integer,String> fun2){
return fun1.andThen(fun2).apply(s);
}
}
四、Stream流
4.1 简介
- Stream 是一个接口 主要是用于对数据进行过滤 类似工厂的流水线
- Stream 提供了两类方法:延迟方法与终结方法
- 延迟方法: Stream 调用方法之后返回值还是Stream对象 还可以继续使用其方法
- 终结方法: Stream 调用方法之后返回值不是Stream对象 不可以继续使用其方法
4.3 常用的方法
方法的名称 | 方法的描述 | 是否是延迟方法 |
---|---|---|
Stream filter(Predicate<? super T> predicate) | 表示对数据进行过滤 | 是 |
void forEach(Consumer<? super T> action) | 表示对Stream的数据遍历 | 否 |
long count() | 表示返回Stream元素的个数 | 否 |
Stream limit(long maxSize) | 表示返回Stream指定长度的元素 | 是 |
Stream map(Function<? super T,? extends R> mapper) | 用于来做数据转换 | 是 |
Stream skip(long n) | 跳过指定的元素 | 是 |
static Stream concat(Stream<? extends T> a, Stream<? extends T> b) | 将两个Stream合并成一个成Stream | 是 |
4.4 案例
有两个 Arraylist 集合,存储队伍中的多个成员姓名,使用stream方式,对以下步骤进行操作
1、第一个队伍只要名字为3个字的成员姓名
2、第一个队伍只要筛选之后的前三个人
3、第二个队伍只要姓张的
4、第二个队伍筛选之后不要前两个人
5、将两个队伍合并成一个队伍
6、合并之后的队伍中的所有人名字变为Person《自定义类型〉对象,并将对象存储到一个List集合中
队伍1:宫本武藏、宋公明、苏有朋、石头人、时传祥、李耳、庄子、洪七公
队伍2:帕瓦罗蒂、张三疯、赵薇薇、张自忠、孛儿只斤铁木真、张天爱、张翠花
Person类:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
测试类:
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;
public class Demo01 {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list1,"宫本武藏","宋公明","苏有朋","石头人","时传祥","李耳","庄子","洪七公");
Collections.addAll(list2,"帕瓦罗蒂","张三疯","赵薇薇","张自忠","孛儿只斤铁木真","张天爱","张翠花");
Stream<String> stream1 = list1.stream();
//第一个队伍只要名字为3个字的成员姓名
//第一个队伍只要筛选之后的前三个人
Stream<String> stream2 = stream1.filter((s) -> s.length() <= 3).limit(3);
Stream<String> stream3 = list2.stream();
//第二个队伍只要姓张的
//第二个队伍筛选之后不要前两个人5、将两个队伍合并成一个队伍
Stream<String> stream4 = stream3.filter((s) -> s.substring(0, 1).equals("张")).skip(2);
//合并
ArrayList<Person> list3 = new ArrayList<>();
Stream.concat(stream2,stream4).forEach(s->list3.add(new Person(s)));
System.out.println(list3);
//Stream.concat(stream2,stream4).map((s)->new Person(s)).forEach(person -> list3.add(person));
//list3.forEach(s-> System.out.println(s));
}
}