enum
enum Operator{
ADD, SUB,MUL,DIV
}
关键字enum可以将一组具名的值的有限集合创建为一种新类型,而这些具名的值可以作为常规的程序组件使用(如在switch语句中的使用).在创建enum时,编译器会自动生成一个相关类,这个类会继承自java.lang.Enum
,并且编译器还会为这个类自动添加两个有用的类方法:
方法 | 说明 |
---|---|
values() | 按照enum常量的声明顺序,生成这些常量值构成的数组 |
valueOf() | 返回当前枚举类型对应名称的枚举常量 |
Enum
Enum中的常用方法
Class<E> getDeclaringClass()
- 返回当前枚举常量对应的枚举类型的Class对象
String name()
- 返回当前枚举常量的名称
int ordinal()
- 返回枚举常量在声明时的排序位置
static <T extends Enum<T>> valueOf(Class<T> enumType,String name)
- 返回指定枚举类型对应名称的枚举常量.
enum与普通类的区别与联系
除了不能继承一个enum,基本上可以将enum看作一个常规的类.因此我们可以向其内添加方法和字段以及实现其它接口,不过在添加方法和字段之前我们应在enum实例序列后添加分号,且不能在定义enum序列之前进行这些操作.还有一点要注意的是,对于enum的构造函数,我们只能将其声明为private.
enum Operator{
ADD("add"), SUB("sum"),MUL("mul"),DIV("div");
private String desc;
Operator(String desc){
this.desc=desc;
}
public String getDesc() {
return desc;
}
}
enum的类型信息
使用反射打印一下前言中Operator的类型信息
public static void main(String[] args) {
System.out.println("是否为final类-----------------------------");
Operator.class.getModifiers();
System.out.println(Modifier.isFinal(Operator.class.getModifiers()));
System.out.println("实现接口信息-------------------------------");
Arrays.stream(Operator.class.getInterfaces()).forEach(System.out::println);
System.out.println("基类信息----------------------------------");
System.out.println(Operator.class.getSuperclass());
System.out.println("构造函数信息-------------------------------");
Arrays.stream(Operator.class.getDeclaredConstructors()).forEach(System.out::println);
System.out.println("字段信息----------------------------------");
Arrays.stream(Operator.class.getDeclaredFields()).forEach(System.out::println);
System.out.println("方法信息----------------------------------");
Arrays.stream(Operator.class.getDeclaredMethods()).forEach(System.out::println);
System.out.println("所有enum常量------------------------------");
Arrays.stream(Operator.class.getEnumConstants()).forEach(System.out::println);
}
注意最后一个方法getEnumConstants()
,该方法可以获取一个enum Class对象中的所有枚举常量.
Enum常量
public static void main(String[] args) {
try {
int add = Operator.class.getDeclaredField("ADD").getModifiers();
System.out.println(Modifier.isStatic(add));//true
System.out.println(Modifier.isFinal(add));//true
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
每个枚举常量使用起来像一个静态内部类实例,且enum像它的父类,不过也仅限于此,我们并不能将枚举常量当类型使用.但我们可以通过在enum定义抽象方法的方式来定制枚举常量的专属行为.以及覆盖某些在enum中的某些方法.
enum Operator{
ADD{
@Override
public void action() {
System.out.println("加法");
}
},
SUB{
@Override
public void action() {
System.out.println("减法");
}
},
MUL{
@Override
public void action() {
System.out.println("乘法");
}
},
DIV{
@Override
public void action() {
System.out.println("除法");
}
};
public abstract void action();
public static void main(String[] args) {
EnumSet<Operator> operators = EnumSet.noneOf(Operator.class);
operators.add(Operator.ADD);
operators.add(Operator.SUB);
for(Operator operator:operators){
operator.action();
}
}
}
EnumSet
EnumSet实现的目的是为了通过enum创建一种代替传统基于int的位标志的替代品,因为传统方法直接操作bit,难以让人理解代码的含义.EnumSet内的元素必须是来自一个enum的enum常量,它是基于long值实现的,一个long值有64位,一个enum常量只需要一个bit来表示它是否存在,如果enum常量多于64个,那么EnumSet会自动扩展.
public static void main(String[] args) {
EnumSet<Operator> operators = EnumSet.allOf(Operator.class);
System.out.println(operators);//[ADD, SUB, MUL, DIV]
}
常用方法
static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType)
- 创建一个包含指定元素类型中所有元素的枚举集
static <E extends Enum<E>> EnumSet<E> of(E first, E... rest)
- 创建一个最初包含指定元素的枚举集
static <E extends Enum<E>> EnumSet<E> range(E from, E to)
- 创建最初包含由两个指定端点定义的范围内的所有元素的枚举集。
static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType)
- 使用指定的元素类型创建一个空的枚举集
EnumMap
EnumMap要求其中的键必须来自一个enum.
常用方法
EnumMap(Class<K> keyType)
构造函数
boolean containsKey(Object key)
如果此映射包含指定键的映射,则返回 true
boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定的值,则返回 true
V get(Object key)
返回到指定键所映射的值
V put(K key, V value)
将指定的值与此映射中的指定键相关联
V remove(Object key)
从该map中删除此key的映射(如果存在)
int size()
返回此地图中键值映射的数量。
使用Enum知识实现一个加减乘除表达式计算器
首先自己写一个栈,也可以使用java自带的
package cn.superstallion.DataStructure;
import java.util.Iterator;
public class Stack<T>implements Iterable <T> {
private class StackIterator implements Iterator<T> {
private int temp=sum;
private Node<T> item=head;
@Override
public boolean hasNext() {
return temp>0;
}
@Override
public T next() {
temp--;
Node<T> tempNode=item;
item=item.next;
return tempNode.element;
}
}
private class Node<T>{
private T element;
private Node<T> next;
}
private Node<T> head;
private int sum;
public Stack(){
}
public void push(T item){
if (head==null){
head=new Node<T>();
head.element=item;
}else {
Node oldHead=head;
head=new Node<T>();
head.element=item;
head.next=oldHead;
}
sum++;
}
public T pop(){
T temp=head.element;
head=head.next;
sum--;
return temp;
}
public boolean isEmpty(){
return sum==0;
}
public int size(){
return sum;
}
@Override
public Iterator<T> iterator() {
return new StackIterator();
}
}
基于栈实现计算器
package cn.superstallion.ClassicalAlgorithm;
import cn.superstallion.DataStructure.Stack;
import java.util.EnumMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Calculator {
private enum Operator{
ADD{
@Override
Double action(Double operandA, Double operandB) {
return operandB+operandA;
}
},
SUB{
@Override
Double action(Double operandA, Double operandB) {
return operandB-operandA;
}
},
MUL{
@Override
Double action(Double operandA, Double operandB) {
return operandB*operandA;
}
},
DIV{
@Override
Double action(Double operandA, Double operandB) {
return operandB/operandA;
}
};
abstract Double action(Double operandA,Double operandB);
public static Operator operatorMapping(String operator){
switch (operator){
case "+":
return ADD;
case "-":
return SUB;
case "*":
return MUL;
case "/":
return DIV;
default:
return null;
}
}
}
static final private EnumMap<Operator,Integer> priority;
static final private String regx = "\\d+|\\D";
static final private Stack<Double> operandStack;
static final private Stack<Operator> operatorStack;
private final String expression;
static {
priority = new EnumMap<>(Operator.class);
operandStack = new Stack<>();
operatorStack = new Stack<>();
priority.put(Operator.ADD, 0);
priority.put(Operator.SUB, 0);
priority.put(Operator.MUL, 1);
priority.put(Operator.DIV, 1);
}
public Calculator(String expression) {
this.expression = expression;
}
public Double calculate() {
Pattern compile = Pattern.compile(regx);
Matcher matcher = compile.matcher(expression);
while (matcher.find()) {
if (matcher.group().matches("\\d+")) {
operandStack.push(Double.valueOf(matcher.group()));
} else if (operatorStack.size() == 0) {
operatorStack.push(Operator.operatorMapping(matcher.group()));
} else {
Operator top = operatorStack.pop();
if (priority.get(Operator.operatorMapping(matcher.group())) >= priority.get(top)) {
operatorStack.push(top);
} else {
Double operandA = operandStack.pop();
Double operandB = operandStack.pop();
operandStack.push(top.action(operandA,operandB));
}
operatorStack.push(Operator.operatorMapping(matcher.group()));
}
}
while (!operatorStack.isEmpty()) {
Double operandA = operandStack.pop();
Double operandB = operandStack.pop();
operandStack.push(operatorStack.pop().action(operandA,operandB));
}
return operandStack.pop();
}
public static void main(String[] args) {
Calculator calculator = new Calculator("1/2+3+2*4");
System.out.println(calculator.calculate());
}
}