1.枚举
1.枚举是在JDK1.5引入的,主要是用来表示一组相同业务的值,比如我们要实现卖车的程序,我们定义一组颜色来穷举这辆车所提供的所有颜色,在没有枚举之前,是这样实现的:
public static int final RED=1;
public static int final GREEN=2;
public static int final BLACK=3;
以上代码存在的问题有: (1)代码可读性低,比如当我们看到数字2时,并不能准确的知道它代表的具体是什么意思。 (2)参数传递容易出错,以上代码类型为int,所以在传递时理论上是可以接受所有的int值的,但只有部分值是有效颜色,所以容易传递值出错。 (3)写法不够清晰,在外层调用时,看到的是一个个数字,不易知道具体的颜色。
2.使用枚举,组织所有的颜色: 使用enum定义,enum和类是同级别的。  枚举命名,所有的枚举值使用全部字母大写的形式。 
使用枚举的优点有: (1)增强了代码的可读性;  (2)减少了传递参数的错误概率;  (3)使用枚举,那么switch的写法非常简单,并且语义也非常清晰。  (4)枚举的代码非常优雅和简洁。
1.1switch判断
1.代码: ColorEnum.java:
public enum ColorEnum {
RED,GREEN,BLACK;
}
App.java:
public class App {
public static void main(String[] args) {
printColor(ColorEnum.GREEN);
}
public static void printColor(ColorEnum colorEnum){
switch(colorEnum){
case RED:
System.out.println("这是一个红色");
break;
case BLACK:
System.out.println("这是一个黑色");
break;
case GREEN:
System.out.println("这是一个绿色");
break;
default:
System.out.println("未知颜色");
break;
}
}
}
2.运行结果: 
1.2枚举常用方法

1.2.1values()使用
以数组形式返回枚举类型的所有成员。  
1.2.2ordinal()使用
获取枚举成员的索引位置。 
1.2.3valueOf()使用
将普通字符串转换为枚举实例。   
1.2.4compare To()使用
比较两个枚举成员在定义时的顺序,返回其相对位置的差值。
使用枚举的下标相减即可,返回的是int类型的值。 
public class App {
public static void main(String[] args) {
ColorEnum colorEnum=ColorEnum.GREEN;
ColorEnum colorEnum2=ColorEnum.RED;
ColorEnum colorEnum3=ColorEnum.BLACK;
System.out.println("颜色顺序是:红色,绿色,黑色");
int result1=colorEnum.compareTo(colorEnum2);
System.out.println("绿色对比红色:"+result1);
int result2=colorEnum.compareTo(colorEnum);
System.out.println("绿色对比绿色:"+result2);
int result3=colorEnum.compareTo(colorEnum3);
System.out.println("绿色对比黑色:"+result3);
int result4=colorEnum2.compareTo(colorEnum3);
System.out.println("红色对比黑色:"+result4);
}

1.3枚举优缺点
1.3.1优点
1.增强了代码的可读性。 2.减少了传递参数的错误概率。 3.switch判断更方便,语法清晰。 4.代码足够简洁、优雅。 5.枚举有内置方法,功能强大。
1.3.2缺点
不可以基础,无法扩展。
2.Lambda表达式
Lambda表达式是JDK8中的一个重要特性,lambda表达式允许通过表达式来代替功能接口 (通过表达式实现业务功能)。lambda表达式就和方法一样,它提高了一个正常的参数列表和 一个使用这些参数的主体,Lambda表达式可以看做是一个匿名函数。
2.1使用lambda的优点
1.提供了更简单的语法和写代码的方式。 2.取代匿名内部类。 3.简化代码,干净整洁。
2.2Lambda语法
1.Lambda表达式的基本语法:
(入参)->{实现代码}
表达式由三部分组成: (1)入参paramaters:类方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可以不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。 (2)->:是被用于的意思。 (3)实现代码:可以是表达式也可以是代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不返回,这里的代码块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不返回。
2.3Lambda基础使用
import java.util.Arrays;
import java.util.List;
public class LambdaTest {
public static void main(String[] args) {
List<String> list= Arrays.asList("Java","MySQL","Lambda","Spring");
for(String item:list){
System.out.println(item);
}
System.out.println();
list.forEach((String item) -> {
System.out.println(item);
});
}
}

注意事项: (1)如果lambda参数的小括号里面只有一个参数,那么小括号可以省略。 (2)如果方法体中只有一句代码,那么大括号可以省略。 (3)如果方法体中只有一条语句,它是return语句,那么大括号可以省略,且去掉return关键字。
2.4Lambda和函数式接口
1.lambda表达式的写法有很多,比如以下这些:  Lambda表达式不能直接使用,它在使用之前必须初始化,lambda表达式必须借助函数式接口(@Functionallnterface)来初始化。
2.4.1函数式接口
1,函数式接口定义:一个接口有且只有一个抽象方法。
注意事项: (1)如果一个接口只有一个抽象方法那么该接口就是一个函数式接口。 (2)如果我们在某个接口上声明了@Functionallnterface注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。
2.函数式接口的定义代码:
@FunctionalInterface
interface MyFunctionalInterface {
void myMethod(Object... args);
}
 3.有了函数式接口之后,我们就可以使用lambda表达式对其实例化: lambda表达式像匿名内部类一样,覆写了接口中的方法。 
2.4.2Lambda的变量捕获
1.在lambda表达式中获取变量和在匿名内部类获取变量的规则一样: 在lambda中如果要获取外部的变量,那么这个变量要么是被final修饰,如果不是被fina修饰的,要保证在使用之前该值没有被修改过,否则会报错。 (1)被final修饰时:  (2)修改变量的值: 
2.5Lambda在集合中的使用
1.Lambda表达式最有价值的作用就是可以配合集合一块使用,比如循环,排序,查找。 Lambda可以配合使用的方法列表如下: 
2.5.1Map中的forEach
1.在没有Lambda之前,我们要循环Map的实现代码如下:
import java.util.HashMap;
import java.util.Map;
public class LambdaTest {
public static void main(String[] args) {
HashMap<String,String> map=new HashMap<String,String>(){{
put("java","java value");
put("Mysql","mysql value");
}};
for (Map.Entry<String,String> item: map.entrySet()) {
System.out.println(item.getKey()+":"+item.getValue());
}
}

2.有了Lambda之后,这样写:
import java.util.HashMap;
public class LambdaTest {
public static void main(String[] args) {
HashMap<String,String> map=new HashMap<String,String>(){{
put("java","java value");
put("Mysql","mysql value");
}};
map.forEach((k,v)->{
System.out.println(k+":"+v);
});
}
 
2.5.2List排序
import java.util.*;
public class LambdaTest {
public static void main(String[] args) {
List<Integer> list=Arrays.asList(5,3,2,7,9);
System.out.println("排序前:"+list);
list.sort((new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
}));
System.out.println("排序后"+list);
}
 
2.5.3实现数据过滤
import java.util.*;
import java.util.stream.Collectors;
public class LambdaTest {
public static void main(String[] args) {
List<String > list=Arrays.asList("java","mysql","Spring","Lambda","Lambda","SpringBoot","Mybatis");
List<String> finds=list.stream().filter(s -> s.equals("Lambda")).collect(Collectors.toList());
System.out.println(finds);
}

2.5.4全部代码
import java.util.*;
import java.util.stream.Collectors;
public class LambdaTest {
public static void main(String[] args) {
List<String > list=Arrays.asList("java","mysql","Spring","Lambda","Lambda","SpringBoot","Mybatis");
List<String> finds=list.stream().filter(s -> s.equals("Lambda")).collect(Collectors.toList());
System.out.println(finds);
}
private static void listSortTest() {
List<Integer> list=Arrays.asList(5,3,2,7,9);
System.out.println("排序前:"+list);
list.sort((new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
}));
System.out.println("排序后"+list);
}
private static void mapTest() {
HashMap<String,String> map=new HashMap<String,String>(){{
put("java","java value");
put("Mysql","mysql value");
}};
for (Map.Entry<String,String> item: map.entrySet()) {
System.out.println(item.getKey()+":"+item.getValue());
}
System.out.println();
map.forEach((k,v)->{
System.out.println(k+":"+v);
});
}
private static void interfaceTest() {
final int count=99;
MyFunctionalInterface myFunctionalInterface=(o)->{
for (Object item: o){
System.out.println("item:"+item);
}
System.out.println("Count"+count);
};
myFunctionalInterface.myMethod("张三","李四","王五");
}
}
2.6Lambda优缺点分析
1.优点: (1)代码简洁,开发迅速。 (2)方便函数式编程。 (3)非常容易进行并行计算。 (4)java引入Lambda改善了集合操作。 2.缺点: (1)代码可读性差。 (2)在非并行计算中,有的计算未必有传统的for性能要搞。 (3)Lambda不容易进行调试。
|