目录
1 枚举背景及定义
枚举是在
JDK1.5
以后引入的。主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式:
public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLACK = 3;
但是常量举例有不好的地方,例如:可能碰巧有个数字
1
,但是他有可能误会为是
RED
,现在我们可以直接用枚举来进行组织,这样一来,就拥有了类型,枚举类型。而不是普通的整形1.
public enum EnumTest2 {
RED,BLACK,GREEEN;
}
优点:将常量组织起来统一进行管理
场景:错误状态码,消息类型,颜色的划分,状态机等等
....
本质:是
java.lang.Enum
的子类,也就是说,自己写的枚举类,就算没有显示的继承
Enum
,但是其默认继承了
这个类。
🚩使用
🎈、switch语句
package Enum;
public enum EnumTest2 {
RED,BLACK,GREEEN;
public static void main(String[] args) {
EnumTest2 enumTest2=EnumTest2.BLACK;
switch (enumTest2){
case RED:
System.out.println("红色");
break;
case BLACK:
System.out.println("黑色");
break;
case GREEEN:
System.out.println("绿色");
break;
default:
System.out.println("没有");
}
}
}
🎈、常用方法
Enum
类的常用方法
方法名称
| 描述 |
values() | 以数组形式返回枚举类型的所有成员 |
ordinal() | 获取枚举成员的索引位置 |
valueOf() | 将普通字符串转换为枚举实例 |
compareTo() | 比较两个枚举成员在定义时的顺序 |
EnumTest2[] enumTest2s=EnumTest2.values();//以数组形式返回枚举类型的所有成员
for (int i = 0; i <enumTest2s.length ; i++) {
System.out.println(enumTest2s[i]+" "+enumTest2s[i].ordinal());
//获取枚举成员的索引位置
}
EnumTest2 c=EnumTest2.valueOf("BLACK");
//valueOf() 将普通字符串转换为枚举实例
System.out.println(c);
System.out.println(RED.compareTo(BLACK));
// //compareTo() 比较两个枚举成员在定义时的顺序 RED 0 BLACK 1 所以返回-1
拿到枚举实例
public static void main(String[] args) {
//拿到枚举实例BLACK
EnumTest2 testEnum = EnumTest2.BLACK;
//拿到枚举实例RED
EnumTest2 testEnum21 = EnumTest2.RED;
System.out.println(testEnum.compareTo(testEnum21));
System.out.println(BLACK.compareTo(RED));
System.out.println(RED.compareTo(BLACK));
}
刚刚说过,在Java当中枚举实际上就是一个类。所以我们在定义枚举的时候,还可以这样定义和使用枚举:
🎈.构造方法
重要:枚举的构造方法默认是私有的
- 1、当枚举对象有参数后,需要提供相应的构造函数
- 2、枚举的构造函数默认是私有的 这个一定要记住
public enum EnumTest2 {
RED(1,"红色"),
BLACK(2,"黑色"),
GREEEN(3,"绿色");
private int ordinal;
private String color;
private EnumTest2(int ordinal, String color) {
this.ordinal = ordinal;
this.color = color;
}
}
因为RED其实是枚举类里的对象。
运用:
public enum EnumTest2 {
RED(1,"红色"),
BLACK(2,"黑色"),
GREEEN(3,"绿色");
private int ordinal;
private String color;
private EnumTest2(int ordinal, String color) {
this.ordinal = ordinal;
this.color = color;
}
public static EnumTest2 getEnumKey(int ordinal){
for(EnumTest2 t:EnumTest2.values()){//前面是每个类对象,后面以数组形式返回枚举类型的所有成员
if(ordinal==t.ordinal){
return t;
}
}
return null;
}
public static void main(String[] args) {
System.out.println(getEnumKey(2));
}
}
2. Lambda表达式
🚩背景
Lambda
表达式是
Java SE 8
中一个重要的新特性。
lambda
表达式允许你通过表达式来代替功能接口。
lambda
表达式就和方法一样,
它提供了一个正常的参数列表和一个使用这些参数的主体
(body,
可以是一个表达式或一个代码块)
。
Lambda
表达式(
Lambda expression
)
,基于数学中的
λ
演算得名,也可称为闭包(
Closure
) 。
🎈Lambda表达式的语法
基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }
parameters-范围 expression-表达
Lambda表达式由三部分组成:
- 1. paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。
- 2. ->:可理解为“被用于”的意思
- 3. 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不返回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不返回。
// 1. 不需要参数,返回值为 2 () -> 2 // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x // 3. 接受2个参数(数字),并返回他们的和 (x, y) -> x + y // 4. 接收2个int型整数,返回他们的乘积 (int x, int y) -> x * y // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) (String s) -> System.out.print(s)
🌈函数式接口
要了解
Lambda
表达式
,
首先需要了解什么是函数式接口,函数式接口定义:
一个接口有且只有一个抽象方法 。
注意:
- 1. 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
- 2. 如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。
- 定义方式:
//函数式接口 @FunctionalInterface interface NoParameterNoReturn1{ //注意只能一个方法 void test(); }
如果声明了@FunctionalInterface,那么就不能定义俩个抽象方法。
但是这种方式也是可以的:
🌈Lambda表达式的基本使用
首先,我们实现准备好几个接口:
//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
void test(int a);
}
//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
void test(int a,int b);
}
//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
int test();
}
//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
int test(int a);
}
//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
int test(int a,int b);
}
我们在上面提到过,
Lambda
可以理解为:
Lambda
就是匿名内部类的简化,实际上是创建了一个类,实现了接口,重写了接口的方法 。
❗无参无返回值
没有使用lambda表达式的时候的调用方式 (无参无返回值):
我们就按第一个 无返回值无参数的调用。
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}
public static void main(String[] args) {
NoParameterNoReturn noParameterNoReturn=new NoParameterNoReturn() {
@Override
public void test() {
System.out.println("这是一个无参无返回值的接口");
}
};//相当于重写了这个类的test方法
noParameterNoReturn.test();
}
有使用lambda表达式的时候的调用方式 (无参无返回值):
NoParameterNoReturn noParameterNoReturn1=()->{
System.out.println("无返回值无参数的 ()->{}");
};
noParameterNoReturn1.test();
❗无返回值一个参数
//无返回值一个参数
OneParameterNoReturn oneParameterNoReturn=(a)->{
System.out.println(a+10);
};
oneParameterNoReturn.test(20);
❗无返回值一个参数
无返回值多个参数
MoreParameterNoReturn moreParameterNoReturn=(a,b)->{
System.out.println(a*b);
};
moreParameterNoReturn.test(10,20);
❗有返回值无参数
//有返回值无参数
NoParameterReturn noParameterReturn=()->{
System.out.println("有返回值无参数");
return 10;
};
System.out.println(noParameterReturn.test());
❗有返回值一个参数
OneParameterReturn oneParameterReturn=(a)->{return a;};
System.out.println(oneParameterReturn.test(10));
❗有返回值多参数
//有返回值多参数
MoreParameterReturn moreParameterReturn=(a,b)->{return a+b;};
System.out.println(moreParameterReturn.test(10, 20));
- 1. 参数类型可以省略,如果需要省略,每个参数的类型都要省略。
- 2. 参数的小括号里面只有一个参数,那么小括号可以省略
- 3. 如果方法体当中只有一句代码,那么大括号可以省略
- 4. 如果方法体中只有一条语句,且是return语句,那么大括号可以省略,且去掉return关键字。
🎈Lambda在集合当中的使用
为了能够让
Lambda
和
Java
的集合类集更好的一起使用,集合当中,也新增了部分接口,以便与
Lambda
表达式对接。
对应的接
口
| 新增的方法 |
Collection | removeIf() spliterator() stream() parallelStream() forEach() |
List | replaceAll() sort() |
Map |
getOrDefault() forEach()
replaceAll() putIfAbsent() remove() replace() computeIfAbsent() computeIfPresent() compute() merge()
|
以上方法的作用可自行查看我们发的帮助手册。我们这里会示例一些方法的使用。注意:
Collection
的
forEach()
方法是从接口 java.lang.Iterable
拿过来的。
🌈Collection接口 forEach() 方法演示
该方法在接口
Iterable
当中,原型如下:
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
该方法表示:对容器中的每个元素执行action指定的动作 。
public static void main(String[] args) {
ArrayList<String> arrayList=new ArrayList<>();
arrayList.add("chenle");
arrayList.add("love");
arrayList.add("zhangyaunfei");
arrayList.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.print(s+" ");
}
});
}
但是如果利用Lambda表达式,代码就会变得很简单
arrayList.forEach(s->{System.out.print(s+" ");});
🌈List接口 sort()方法的演示
sort
方法源码:该方法根据
c
指定的比较规则对容器元素进行排序。
arrayList.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//这里比较的是长度
return o1.length()-o2.length();
}
});
System.out.println(arrayList);
但是如果利用Lambda表达式,代码就会变得很简单
arrayList.sort((o1,o2)->o1.length()-o2.length());
System.out.println(arrayList);
🌈Map接口HashMap 的 forEach()
作用是对Map中的每个映射执行action指定的操作。
public static void main(String[] args) {
HashMap<String,Integer>hashMap=new HashMap<>();
hashMap.put("chenle",2);
hashMap.put("zhangyaunfei",3);
hashMap.put("cl",4);
hashMap.forEach(new BiConsumer<String, Integer>() {
@Override
public void accept(String s, Integer integer) {
System.out.println(s+" "+integer);
}
});
}
用Lambda表达式可以
hashMap.forEach((k,v)-> System.out.println(k+" "+v));
🎈总结
Lambda表达式的优点很明显,在代码层次上来说,使代码变得非常的简洁。缺点也很明显,代码不易读。
优点:
- 1. 代码简洁,开发迅速
- 2. 方便函数式编程
- 3. 非常容易进行并行计算
- 4. Java 引入 Lambda,改善了集合操作
缺点:
- 1. 代码可读性变差
- 2. 在非并行计算中,很多计算未必有传统的 for 性能要高
- 3. 不容易进行调试
阶段性学习尾声了。