一、枚举
1.引入
编写季节类(Season),该类只有四个对象(spring,summer,autumn,winter)
public class Test { public static void main(String[] args) { System.out.println(Season.spring); System.out.println(Season.summer); System.out.println(Season.autumn); System.out.println(Season.winter); } } public class Season { public static final Season spring = new Season("春天", "万物复苏"); public static final Season summer = new Season("夏天", "夏日炎炎"); public static final Season autumn = new Season("秋天", "秋高气爽"); public static final Season winter = new Season("冬天", "银装素裹"); private String name; private String info; private Season() { } private Season(String name, String info) { this.name = name; this.info = info; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Override public String toString() { return "Season [name=" + name + ", info=" + info + "]"; } }
2.概念
枚举(enum)全称为 enumeration, 是 JDK 1.5 中引入的新特性。
3.语法
public enum Color{
//默认添加 public static final Color
RED,GREEN,BLUE;
}
4.本质
尽管枚举看起来像是一种新的数据类型,实际上,枚举就是一种受限制的类,并且具有自己的方法。创建自己的enum类时,这个类继承自 java.lang.Enum。
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable{
...
}
5.特点
- 枚举就是一个受限制的类,默认继承Enum
- 枚举的第一行必须定义该枚举类型的对象
- 枚举类型对象默认添加: public static final 类型
- 枚举没有继承明确类(自定义枚举类默认继承Enum,Enum默认继承Object)
- 枚举类不能被继承
- 枚举里可以有构造方法、成员方法、静态方法、抽象方法
- 枚举可以实现接口
- 枚举里没有定义方法,可以在最后一个对象后面加逗号、分号或什么都不加
6.优势
增强代码可读性
枚举型可直接与数据库交互
switch语句优势
编译优势
(枚举类编译时,没有把常量值编译到代码中,即使常量值发生改变,也不会影响引用常量的类 )
将常量组织起来,统一管理
去除equals两者判断 由于常量值地址唯一,使用枚举可以直接通过“==”进行两个值之间的对比,性能会有所提高
7.枚举的方法
方法名 | 解释 |
---|---|
Enum.valueOf(Class enumType, String name) | 根据字符串找到该枚举类中的对象 |
public static void values() | 获取该枚举类对象数组 |
public static void valueOf(String args0) | 根据字符串获取该枚举类中的对象 |
public final String name() | 获取该枚举对象名字 |
public final Class getDeclaringClass() | 获取枚举对象的枚举类型相对应的Class对象 |
public final int hashCode() | 获取该枚举对象的hash值 |
public final int compareTo(E o) | 两个枚举对象进行比较 |
public final boolean equals(Object other) | 比较两个枚举对象是否相同 |
8.枚举案例 - 状态机
enum Signal{RED, YELLOW, GREEN}
public class EnumTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入信号灯:RED,YELLOW,GREEN");
Signal signal = Signal.valueOf(scan.next());
String instruct = getTrafficInstruct(signal);
System.out.println(instruct);
scan.close();
}
public static String getTrafficInstruct(Signal signal) {
String instruct = "信号灯故障";
switch (signal) {
case RED:
instruct = "红灯停";
break;
case YELLOW:
instruct = "黄灯请注意";
break;
case GREEN:
instruct = "绿灯行";
break;
default:
break;
}
return instruct;
}
}
9.枚举案例 - 错误码
public enum ErrorCodeEn {
Ok(1,"成功"),ERROR_A(2,"错误A"),ERROR_B(3,"错误B");
private int code;//状态码
private String description;//状态信息
ErrorCodeEn(){}
ErrorCodeEn(int code,String description){
this.code = code;
this.description = description;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
}
10.枚举案例 - 组织枚举
含义:可以将类型相近的枚举通过接口或类组织起来(但是一般用接口方式进行组织)
原因是:
Java接口在编译时会自动为enum类型加上public static修饰符;
Java类在编译时会自动为 enum 类型加上static修饰符;
就是说,在类中组织 enum,如果你不给它修饰为 public,那么只能在本包中进行访问。
public interface IErrorCode {
enum LoginErrorCodeEn implements INumberEnum{
OK(1,"登录成功"),ERROR_A(-1,"验证码错误"),ERROR_B(-2,"密码错误"),ERROR_C(-3,"用户已登录");
private int code;
private String description;
LoginErrorCodeEn(int code,String description){
this.code = code;
this.description = description;
}
@Override
public int getCode() {
return code;
}
@Override
public String getDescription() {
return description;
}
}
enum RigsterErrorCodeEn implements INumberEnum{
OK(1,"注册成功"),ERROR_A(-1,"账号已存在");
private int code;
private String description;
RigsterErrorCodeEn(int code,String description){
this.code = code;
this.description = description;
}
@Override
public int getCode() {
return code;
}
@Override
public String getDescription() {
return description;
}
}
}
interface INumberEnum {
int getCode();
String getDescription();
}
11.枚举案例 - 策略枚举
优点:这种枚举通过枚举嵌套枚举的方式,将枚举常量分类处理。
这种做法虽然没有switch语句简洁,但是更加安全、灵活。
public enum Salary {
JAVA(SalaryType.TEACHER),
HTML(SalaryType.TEACHER),
PYTHON(SalaryType.TEACHER),
PRINCIPAL(SalaryType.ADMINISTRATION);//校长
private final SalaryType salaryType;
Salary(SalaryType salaryType){
this.salaryType = salaryType;
}
//baseSalary-底薪 classHour-课时 teachingHourSubsidy-课时费 achievements-绩效
double getSalary(double baseSalary,int classHour,double teachingHourSubsidy,double achievements){
return salaryType.getSalary(baseSalary, classHour, teachingHourSubsidy, achievements);
}
//策略枚举
private enum SalaryType {
TEACHER {//老师
@Override
double getSalary(double baseSalary, int classHour, double teachingHourSubsidy,
double achievements) {
return baseSalary + classHour*teachingHourSubsidy + achievements;
}
},
ADMINISTRATION {//行政人员
@Override
double getSalary(double baseSalary, int classHour, double teachingHourSubsidy,
double achievements) {
return baseSalary + achievements;
}
};
abstract double getSalary(double baseSalary,int classHour,double teachingHourSubsidy,double achievements);
}
}
12.枚举工具类 - EnumSet 和 EnumMap
Java 中提供了两个方便操作enum的工具类——EnumSet 和 EnumMap。
EnumSet :枚举类型的高性能 Set实现。它要求放入它的枚举常量必须属于同一枚举类型。
EnumMap :专门为枚举类型量身定做的 Map 实现。虽然使用其它的 Map 实现(如HashMap)也能完成枚举类型实例到值得映射,但是使用 EnumMap 会更加高效,因为它只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以 EnumMap 使用数组来存放与枚举类型对应的值。这使得 EnumMap 的效率非常高。
public class EnumTest {
public static void main(String[] args) {
//EnumSet的使用
//把Signal枚举中所有对象抽取到Set集合中
EnumSet<Signal> signalSet = EnumSet.allOf(Signal.class);
for (Enum<Signal> en : signalSet) {
System.out.println(en);
}
//EnumMap的使用
EnumMap<Signal,Object> enumMap = new EnumMap<>(Signal.class);
enumMap.put(Signal.RED, "红灯");
enumMap.put(Signal.YELLOW, "黄灯");
enumMap.put(Signal.GREEN, "绿灯");
//把所有的映射关系对象抽取到Set集合中
Set<Entry<Signal, Object>> entrySet = enumMap.entrySet();
for (Entry<Signal, Object> entry : entrySet) {
Signal key = entry.getKey();
Object value = entry.getValue();
System.out.println(key + " -- " + value);
}
}
}
enum Signal{RED, YELLOW, GREEN}
二、集合
1. 集合的概念
- 集合是Java API所提供的一系列类,可以用于动态存放多个对象。–集合只能存对象
- 集合与数组的不同在于,集合是大小可变的序列,而且元素类型可以不受限定,只要是引用类型。(集合中不能放基本数据类型,但可以放基本数据类型的包装类)
- 集合类全部支持泛型,是一种数据安全的用法。
2.集合与数组的不同
数组:一旦初始化后长度不可变,元素类型受限定(String类型的数组只能装String的数据),数组可以存储基本数据类型
集合:长度可变的序列,元素类型不受限定(一个集合可以存储多个数据类型的元素),集合只能存储引用数据类型
3.集合框架图
Java的集合框架从整体上可以分为两大家族。
- Collection(接口)家族。该接口下的所有子孙均存储的是单一对象。 Add(s)
- Map(接口)家族。该接口下的所有子孙均存储的是key-value(键值对)形式的数据。
另外还有三个分支,均是为上述两大家族服务的。
- Iterator(迭代器)家族。主要用于遍历Colleciton接口的及其子类而设计。
- Comparator(比较器), 在集合中存储对象时候,用于对象之间的比较
- Collecitons是工具类。注意该类名带个,一般就表示工具类。里面提供了多静态方法,来对集合进行操作。
4.初识Arraylist
感受一个集合对象可以存储多个数据类型
public class Test { public static void main(String[] args) { ArrayList list = new ArrayList(); //添加数据 list.add(100);//Integer.valueOf(100) list.add(123.123);//Double.valueOf(123.123) list.add("abcdef"); } }
缺点:不方便管理
5.ArrayList的使用
案例及解析:
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public class Test { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); //添加数据 list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("ddd"); list.add("eee"); //设置指定下标上的元素 list.set(1, "fff"); //获取指定下标上的元素 String str = list.get(1); System.out.println("获取指定下标上的元素:" + str);//fff //获取元素个数 int size = list.size(); System.out.println("获取元素个数:" + size);//5 //在指定下标上添加元素 list.add(2, "ggg"); ArrayList<String> newList1 = new ArrayList<>(); Collections.addAll(newList1, "aaa","bbb","ccc","ccc");//利用集合工具类(Collections)批量添加元素 list.addAll(newList1);//将newList1中所有的元素都添加到list集合里末尾的位置 ArrayList<String> newList2 = new ArrayList<>(); Collections.addAll(newList2, "xxx","xxx","yyy","yyy","zzz","zzz");//利用集合工具类(Collections)批量添加元素 list.addAll(3, newList2);//将newList2中所有的元素都添加到list集合里指定下标的位置 //清空集合里所有的元素 //list.clear(); System.out.println("判断集合中是否包含指定元素:" + list.contains("侯小康"));//true System.out.println("判断集合中是否包含指定集合:" + list.containsAll(newList1));//true System.out.println("获取元素在集合中第一次出现的下标:" + list.indexOf("ccc"));//12 System.out.println("获取元素在集合中最后一次出现的下标:" + list.lastIndexOf("ccc"));//13 //没有-true,有-false System.out.println("判断集合里是否没有元素:" + list.isEmpty());//false list.remove(9);//通过下标删除元素 list.remove("水菜丽");//通过数据删除元素 list.removeAll(newList1);//将list中有newList1的元素全部删除(去除交集) list.retainAll(newList2);//将list中有newList2的元素全部保留(保留交集) List<String> subList = list.subList(1, 4);//从开始下标处(包含)截取到结束下标处(排他)的元素,返回新的集合 //将集合转换为数组 Object[] array1 = subList.toArray(); System.out.println(Arrays.toString(array1));//[xxx, yyy, yyy] //将集合转换为指定类型的数组 String[] array2 = new String[3]; subList.toArray(array2); System.out.println(Arrays.toString(array2));//[xxx, yyy, yyy] System.out.println("-----------------------------------------"); //遍历集合 -- for循环 for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } System.out.println("-----------------------------------------"); //遍历集合 -- foreach for (String element : list) { System.out.println(element); } System.out.println("-----------------------------------------"); //遍历集合 -- Iterator Iterator<String> it = list.iterator(); while(it.hasNext()){//判断是否有可迭代的元素 String next = it.next();//获取下一个元素 System.out.println(next); } System.out.println("-----------------------------------------"); //遍历集合 -- ListIterator ListIterator<String> listIterator = list.listIterator(); while(listIterator.hasNext()){//判断是否有可迭代的元素 String next = listIterator.next();//获取下一个元素 System.out.println(next); } } }