# Lambda表达式
### 例子
- 例子1
```java
//匿名内部类
Comparator<Integer> cpt = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
TreeSet<Integer> set = new TreeSet<>(cpt);
System.out.println("=========================");
//使用lambda表达式
Comparator<Integer> cpt2 = (x,y) -> Integer.compare(x,y);
TreeSet<Integer> set2 = new TreeSet<>(cpt2);
```
- 例子2 System.out::println
```java
// 创建出一个数组
List<String> strList = Arrays.asList("YangHang", "AnXiaoHei", "LiuPengFei");
strList.forEach(System.out::println);
```
### 分别使用成员内部类、局部内部类、静态内部类、匿名内部类方式实现Runnable的run()方法并创建和启动线程,如下所示:
```java
public class LambdaDemo {
/**
* 成员内部类
*/
class MyThread01 implements Runnable{
@Override
public void run() {
System.out.println("成员内部类:用Lambda语法创建线程吧!");
}
}
/**
* 静态内部类
*/
static class MyThread02 implements Runnable{
@Override
public void run() {
System.out.println("静态内部类:对啊,用Lambda语法创建线程吧!");
}
}
public static void main(String[] args) {
/**
* 局部内部类
*/
class MyThread03 implements Runnable{
@Override
public void run() {
System.out.println("局部内部类:用Lambda语法创建线程吧!");
}
}
/**
* 匿名内部类
*/
Runnable runnable = new Runnable(){
@Override
public void run() {
System.out.println("匿名内部类:求求你,用Lambda语法创建线程吧!");
}
};
//成员内部类方式
LambdaDemo lambdaDemo = new LambdaDemo();
MyThread01 myThread01 =lambdaDemo.new MyThread01();
new Thread(myThread01).start();
//静态内部类方式
MyThread02 myThread02 = new MyThread02();
new Thread(myThread02).start();
//局部内部类
MyThread03 myThread03 = new MyThread03();
new Thread(myThread03).start();
//匿名内部类的方式
new Thread(runnable).start();
}
}
```
- 使用lambda表达式启动线程
```java
//Lambda方式
new Thread(() -> System.out.println("使用Lambda就对了")).start();
```
## lambda语法
- Lambda表达式在Java语言中引入了一个操作符**“——>”**,该操作符被称为Lambda操作符或箭头操作符。它将Lambda分为两个部分:
左侧:指定了Lambda表达式需要的所有参数
右侧:制定了Lambda体,即Lambda表达式要执行的功能。
eg:(parameters) -> expression
或 (parameters) ->{ statements; }
### lambda表达式特征(语法格式)
```java
@Data
public class LambdaExpression {
interface LambdaInterface01 {
public void fun(String str);
}
interface LambdaInterface02 {
public void fun(String str, int i);
}
interface LambdaInterface33 {
public int sum(int x, int y);
}
interface LambdaInterface34 {
public String fun();
}
interface LambdaInterface666{
public void fun();
}
// 基于lambda表达式实现
public static void main(String[] args) {
//一个string 入参;无返回值
LambdaInterface01 lambdaInterface01 = (String str) -> System.out.println("我是第" + str + "个Lambda表达式");
lambdaInterface01.fun("1");
// 两个参数,无返回值
LambdaInterface02 lambdaInterface02 = (x, y) -> System.out.println(x + "666" + y);
lambdaInterface02.fun("华夏", 666);
//两参数,有返回值
LambdaInterface33 lambdaInterface33 = (x, y) -> {
int sum = x + y;
return sum;
};
int sum = lambdaInterface33.sum(100, 200);
System.err.println("100+200=" + sum);
//无参,有返回
LambdaInterface34 lambdaInterface34= ()->{
System.out.println("这是无参有返回");
return "无参有返回";
};
String result = lambdaInterface34.fun();
System.err.println(result);
//无参,无返回
LambdaInterface666 lambdaInterface666= ()-> System.out.println("无参无返回的表达");
lambdaInterface666.fun();
}
}
```
# 函数式接口
# 方法引用和构造器调用
### 方法引用
- 三种表现形式
1. 对象::实例方法名
2. 类::静态方法名
3. 类::实例方法名 (lambda参数列表中第一个参数是实例方法的调用 者,第二个参数是实例方法的参数时可用)
```java
public void test() {
/**
*注意:
* 1.lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!
* 2.若lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method
*
*/
Consumer<Integer> con = (x) -> System.out.println(x);
con.accept(100);
// 方法引用-对象::实例方法
Consumer<Integer> con2 = System.out::println;
con2.accept(200);
// 方法引用-类名::静态方法名
BiFunction<Integer, Integer, Integer> biFun = (x, y) -> Integer.compare(x, y);
BiFunction<Integer, Integer, Integer> biFun2 = Integer::compare;
Integer result = biFun2.apply(100, 200);
// 方法引用-类名::实例方法名
BiFunction<String, String, Boolean> fun1 = (str1, str2) -> str1.equals(str2);
BiFunction<String, String, Boolean> fun2 = String::equals;
Boolean result2 = fun2.apply("hello", "world");
System.out.println(result2);
}
```
### 构造器引用
- 格式:ClassName::new
```java
public void test2() {
// 构造方法引用 类名::new
Supplier<Employee> sup = () -> new Employee();
System.out.println(sup.get());
Supplier<Employee> sup2 = Employee::new;
System.out.println(sup2.get());
// 构造方法引用 类名::new (带一个参数)
Function<Integer, Employee> fun = (x) -> new Employee(x);
Function<Integer, Employee> fun2 = Employee::new;
System.out.println(fun2.apply(100));
}
```
### 数组引用
- 格式:Type[]::new
```java
public void test(){
// 数组引用
Function<Integer, String[]> fun = (x) -> new String[x];
Function<Integer, String[]> fun2 = String[]::new;
String[] strArray = fun2.apply(10);
Arrays.stream(strArray).forEach(System.out::println);
}
```
# Stream API
# Stream 流的使用
## 基本用法
- map 取对象的某一列
```java
// Stream流
List<String> userNameList = userList.stream().map(User::getName).collect(Collectors.toList());
```
- filter 过滤
```java
// 获取userName不为空的user的List
List<User> userList = userList.stream().filter(user-> user.getName() != null).collect(Collectors.toList());
```
- groupingBy 分组
```java
Map<String, List<User>> map =userList.stream().collect( Collectors.groupingBy(User::getAge, Collectors.toList()));
```
- sum 求和
```java
// int、double、long:
double max = userList.stream().mapToDouble(User::getHeight).sum();
```
- Map和List互转
//list转map
```java
//list转map
Map<String, User> userMap= userList.stream().collect(Collectors.toMap(User::getName, Function.identity(),(key1, key2)->key2));
```
//map转list
```java
//map转list
List<User> userList = userMap.entrySet().stream().map(e ->e.getValue()).collect(Collectors.toList());
```
## 做判断
- anyMatch() 判断的条件里,任意一个元素成功,返回true;
```java
userList.stream().anyMatch(user -> user.getHeight() > 175);
```
- allMatch() 判断条件里的元素,所有的都是,返回true;
```java
userList.stream().allMatch(user -> user.getHeight() > 175);
```
- noneMatch() 判断条件里的元素,所有的都不是,返回true
```java
userList.stream().noneMatch(user -> user.getHeight() > 175);
```
- 求取目标和
```java
userList.stream().filter(user -> user.getHeight() > 175).count();
```
## 合并list
- 合并多个一维list
```java
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(4, 5, 6);
List<Integer> list3 = Arrays.asList(7, 8, 9);
List<Integer> mergedList = Stream.of(list1, list2, list3).flatMap(Collection::stream).collect(Collectors.toList());
System.out.println(mergedList);// [1, 2, 3, 4, 5, 6, 7, 8, 9]
```
- 合并嵌套list
```java
List<String> list1 = Arrays.asList("张三", "李四", "王二麻子");
List<String> list2 = Arrays.asList("111", "222", "333");
// 合并前
List<List<String>> lists = Arrays.asList(list1, list2);
System.out.println(lists);
// 合并后
List<String> mergedList = lists.stream().flatMap(Collection::stream).collect(Collectors.toList());
System.out.println(mergedList);
```
## 分页
```java
Map<String,Object> map = Maps.newHashMap();
List list = new ArrayList();
//list -> 当前页所有数据
map.put("list",list.stream().skip((long) (pageNo - 1) * pageSize).limit(pageSize).collect(Collectors.toList()));
//count -> 记录总条数
map.put("count",list.size());
```
# 接口中的默认方法和静态方法
# 新时间日期API
LocalDate | LocalTime | LocalDateTime
表示日期的LocalDate
表示时间的LocalTime
表示日期时间的LocalDateTime
# 补充知识---Java内部类
### 普通内部类(成员内部类)
```java
/**
* 普通内部类
* 创建内部类的对象,首先需要创建外部类对象
* 外部类对象去调普通内部类的构造器
* 外部对象.new 内部类构造器
*/
@Data
public class InnerClassTest {
// 外部类的属性
public int outFiled1 = 1;
protected int outFiled2 = 2;
int outFiled3 = 3;
private int outFiled4 = 4;
// 无参构造
public InnerClassTest() {
// System.out.println("创建"+this.getClass().getSimpleName()+"对象");
// 创建普通内部类对象
InnerClassA innerobj = new InnerClassA();
System.err.println("创建" + this.getClass().getSimpleName() + "对象");
System.out.println("其内部类的 field1 字段的值为: " + innerobj.innerFiled1);
System.out.println("其内部类的 field2 字段的值为: " + innerobj.innerFiled2);
System.out.println("其内部类的 field3 字段的值为: " + innerobj.innerFiled3);
System.out.println("其内部类的 field4 字段的值为: " + innerobj.innerFiled4);
}
// 普通内部类
@Data
public class InnerClassA {
public int innerFiled1 = 5;
protected int innerFiled2 = 6;
int innerFiled3 = 7;
private int innerFiled4 = 8;
// 内部无参构造
public InnerClassA() {
System.err.println("创建" + this.getClass().getSimpleName() + "对象");
System.out.println("其内部类的 field1 字段的值为: " + outFiled1);
System.out.println("其内部类的 field2 字段的值为: " + outFiled2);
System.out.println("其内部类的 field3 字段的值为: " + outFiled3);
System.out.println("其内部类的 field4 字段的值为: " + outFiled4);
}
}
public static void main(String[] args) {
// 创建外部类对象
InnerClassTest outerObj = new InnerClassTest();
// 创建普通内部类对象,需要外部类对象去调普通内部类的构造器
InnerClassA innerClassA = outerObj.new InnerClassA();
}
}
```
### 静态内部类
```Java
/**
* 静态内部类
* 创建静态内部类对象,无需创建外部类对象。可直接创建内部类对象
* new.外部类名.静态内部类名
*/
@Data
public class InnerClass01 {
public int field1 = 999;
public InnerClass01() {
System.out.println("创建 " + this.getClass().getSimpleName() + " 对象");
// 创建静态内部类对象
StaticClass innerObj = new StaticClass();
System.out.println("其内部类的 field1 字段的值为: " + innerObj.field1);
System.out.println("其内部类的 field2 字段的值为: " + innerObj.field2);
System.out.println("其内部类的 field3 字段的值为: " + innerObj.field3);
System.out.println("其内部类的 field4 字段的值为: " + innerObj.field4);
}
static class StaticClass {
public int field1 = 1;
protected int field2 = 2;
int field3 = 3;
private int field4 = 4;
// 静态内部类中可以定义 static 属性
static int field5 = 5;
public StaticClass() {
System.out.println("创建 " + StaticClass.class.getSimpleName() + " 对象");
// System.out.println("其外部类的 field1 字段的值为: " + field1); // 编译错误!!
}
}
public static void main(String[] args) {
// 无需依赖外部类对象,直接创建内部类对象
InnerClass01.StaticClass staticClassObj = new InnerClass01.StaticClass();
System.err.println(staticClassObj);
// InnerClass01 innerClass01 = new InnerClass01();
}
}
```
### 匿名内部类
```java
/**
* 匿名内部类---只能写在方法中
* 在方法参数中新建一个接口对象 / 类对象,并且实现这个接口声明 / 类中原有的方法
* 1、直接 new 一个接口,并实现这个接口声明的方法,在这个过程其实会创建一个匿名内部类实现这个接口,并重写接口声明的方法,然后再创建一个这个匿名内部类的对象并赋值给前面的 OnClickListener 类型的引用;
* 2、new 一个已经存在的类 / 抽象类,并且选择性的实现这个类中的一个或者多个非 final 的方法,这个过程会创建一个匿名内部类对象继承对应的类 / 抽象类,并且重写对应的方法。
* 同样的,在匿名内部类中可以使用外部类的属性,但是外部类却不能使用匿名内部类中定义的属性,因为是匿名内部类,因此在外部类中无法获取这个类的类名,也就无法得到属性信息。
*
*/
@Data
public class InnerClass02 {
public int field1 = 1;
protected int field2 = 2;
int field3 = 3;
private int field4 = 4;
public InnerClass02() {
System.out.println("创建 " + this.getClass().getSimpleName() + " 对象");
}
// 自定义接口
interface OnClickListener {
void onClick(Object obj);
}
interface OnClickListener02 {
void onClick(Object obj);
}
private void anonymousClassTest() {
// 在这个过程中会新建一个匿名内部类对象,
// 这个匿名内部类实现了 OnClickListener 接口并重写 onClick 方法
OnClickListener clickListener = new OnClickListener() {
// 可以在内部类中定义属性,但是只能在当前内部类中使用,
// 无法在外部类中使用,因为外部类无法获取当前匿名内部类的类名,
// 也就无法创建匿名内部类的对象
int field = 1;
@Override
public void onClick(Object obj) {
System.out.println("对象 " + obj + " 被点击");
System.out.println("其外部类的 field1 字段的值为: " + field1);
System.out.println("其外部类的 field2 字段的值为: " + field2);
System.out.println("其外部类的 field3 字段的值为: " + field3);
System.out.println("其外部类的 field4 字段的值为: " + field4);
}
};
// new Object() 过程会新建一个匿名内部类,继承于 Object 类,
// 并重写了 toString() 方法
clickListener.onClick(new Object() { //调用匿名内部类
@Override
public String toString() {
return "obj1";
}
});
}
public static void main(String[] args) {
// 创建外部类的对象
InnerClass02 outObj = new InnerClass02();
// 用外部类去调这个属性方法
outObj.anonymousClassTest();
}
}
```
### 局部内部类
```java
/**
* 局部内部类
* 只能在当前方法中使用
*/
@Data
public class InnerClass03 {
public int field1 = 1;
protected int field2 = 2;
int field3 = 3;
private int field4 = 4;
public InnerClass03() {
System.out.println("创建" + this.getClass().getSimpleName() + "对象");
}
private void localInnerClassTest() {
//局部内部类A,只能在当前方法中使用
class A {
// static int field = 1; // 编译错误!局部内部类中不能定义 static 字段
// 局部内部类的构造
public A() {
System.out.println("创建 " + A.class.getSimpleName() + " 对象");
System.out.println("其外部类的 field1 字段的值为: " + field1);
System.out.println("其外部类的 field2 字段的值为: " + field2);
System.out.println("其外部类的 field3 字段的值为: " + field3);
System.out.println("其外部类的 field4 字段的值为: " + field4);
}
}
A a = new A();
if (true){
// 代码块中的局部内部类
// 局部内部类B 只能在当前代码块中使用
class B{
public B() {
System.out.println("创建 " + B.class.getSimpleName() + " 对象");
System.out.println("其外部类的 field1 字段的值为: " + field1);
System.out.println("其外部类的 field2 字段的值为: " + field2);
System.out.println("其外部类的 field3 字段的值为: " + field3);
System.out.println("其外部类的 field4 字段的值为: " + field4);
}
}
B b = new B();
}
// B b1 = new B(); // 编译错误!不在类 B 的定义域内,找不到类 B
}
public static void main(String[] args) {
InnerClass03 innerClass03 = new InnerClass03();
innerClass03.localInnerClassTest();
}
}
```