两个相关的枚举映射?

时间:2015-09-22 06:18:43

标签: java enums

我有两个相关的枚举。

Enum1:

public enum HttpMethodName 
{
    GET, POST, PUT, DELETE; 
}

Enum2:

public enum ProtocolOperation {
    CREATE(1), RETRIEVE(2), UPDATE(3), DELETE(4), NOTIFY(5);


    private BigInteger operationId;

    public BigInteger getOperationId() {
        return operationId;
    }

    private ProtocolOperation(int operationId) {
        this.operationId = BigInteger.valueOf(operationId);
    }
}

枚举值的映射为:

Create--> POST
Retrieve--> GET
Update--> PUT
Delete--> DELETE
Notify---> POST

因此除了POST个案例之外,值之间存在一对一的映射,根据条件可以有CreateNotify两个值。

我在考虑将映射保持为List

    public enum HttpMethodName 
    {

        POST(new List(ProtocolOperation.CREATE, ProtocolOperation.NOTIFY)) ,GET ( new List(ProtocolOperation.RETRIEVE) ) ,
PUT (new List(ProtocolOperation.UPDATE) ,DELETE(new List(ProtocolOperation.DELETE) ;

        List<ProtocolOperation > ops;
        HttpMethodName (List<ProtocolOperation> ops)
        {
            this.ops = ops;
        }
    }

有更好的方法吗?

修改

我希望从HttpMethodName <----> ProtocolOperation

映射两种方式

3 个答案:

答案 0 :(得分:8)

为什么你觉得你目前的方法不能令人满意?

如果不了解您的疑虑,我只能建议删除样板:

import static ProtocolOperation.*;

public enum HttpMethodName {
    GET(RETRIEVE),
    POST(CREATE, NOTIFY),
    PUT(UPDATE),
    DELETE(ProtocolOperation.DELETE);

    final List<ProtocolOperation> ops;

    HttpMethodName(ProtocolOperation... ops) {
        this.ops = Collections.unmodifiableList(Arrays.asList(ops));
    }
}

UPD:

如果您希望以两种方式进行映射,则首先将映射从ProtocolOperation硬编码到HttpMethodName(因为它不需要列表)并在{{{{}}中创建一个简单的搜索方法1}}:

MttpMethodName

由于您拥有恒定且数量较少的值,因此无需在public enum ProtocolOperation { CREATE(1, HttpMethodName.POST), RETRIEVE(2, HttpMethodName.GET), UPDATE(3, HttpMethodName.PUT), DELETE(4, HttpMethodName.DELETE), NOTIFY(5, HttpMethodName.POST); private BigInteger operationId; private HttpMethodName methodName; public BigInteger getOperationId() { return operationId; } public HttpMethodName getMethodName() { return methodName; } private ProtocolOperation(int operationId, HttpMethodName httpMethodName) { this.methodName = httpMethodName; this.operationId = BigInteger.valueOf(operationId); } } public enum HttpMethodName { GET, POST, PUT, DELETE; List<ProtocolOperation> getProtocolOperations() { List<ProtocolOperation> ops = new ArrayList<ProtocolOperation>(2); for (ProtocolOperation op : ProtocolOperation.values()) { if (op.getMethodName() == this) { ops.add(op); } } return ops; } } 中创建最终静态地图以提供向后映射,线性搜索对于您的情况来说足够快。

答案 1 :(得分:4)

使用箭头显示从ProtocolOperationHttpMethodName的映射,因此它们是简单的引用,而不是列表。

反向映射可以是一个静态方法,它迭代匹配的5个枚举值。只有5个值,所以顺序搜索足够快,除非你是在一个非常紧凑的循环中做的事情,在这种情况下这是不可能的。此外,在分析器说您遇到问题之前,不应该对性能进行编码。

您按照以下步骤操作:

// From ProtocolOperation to HttpMethodName
HttpMethodName method = ProtocolOperation.CREATE.getHttpMethodName();

// From HttpMethodName to ProtocolOperation
ProtocolOperation op = ProtocolOperation.forMethod(HttpMethodName.GET);

实现:

public enum HttpMethodName 
{
    GET, POST, PUT, DELETE; 
}
public enum ProtocolOperation {
    CREATE  (1, HttpMethodName.POST),
    RETRIEVE(2, HttpMethodName.GET),
    UPDATE  (3, HttpMethodName.PUT),
    DELETE  (4, HttpMethodName.DELETE),
    NOTIFY  (5, HttpMethodName.POST);

    private final int            operationId;
    private final HttpMethodName httpMethodName;

    private ProtocolOperation(int operationId, HttpMethodName httpMethodName) {
        this.operationId = operationId;
        this.httpMethodName = httpMethodName;
    }

    public int getOperationId() {
        return this.operationId;
    }

    public HttpMethodName getHttpMethodName() {
        return this.httpMethodName;
    }

    public static List<ProtocolOperation> forMethod(HttpMethodName httpMethodName) {
        List<ProtocolOperation> ops = new ArrayList<>();
        for (ProtocolOperation op : values())
            if (op.httpMethodName == httpMethodName)
                ops.add(op);
        return ops;
    }
}

答案 2 :(得分:1)

我会将逻辑与枚举分开。你的方法是紧密耦合,弹性较小。使用这种带变换metod的库你会更灵活

private static final Map<HttpMethodName , ProtocolOperation> mapping = new HashMap<>();
static {
mapping .put(Create, POST);
// rest of methods
}

这里是你的映射方法的主体(我正在使用Jdk8):

public static Optional<HttpMethodName > map(ProtocolOperation  op){
 if (!mapping.containsKey(op)){
   return Optional.empty();
 }
  return Optional.of(mapping.get(op));
}

简而言之:枚举不应该有任何与之关联的业务逻辑,对于映射和转换,应该使用外部方法(utils)。

<强>更新: 正如@Andreas正确指出的那样,在这个特殊的例子中,映射是固定的,不应该扩展,你可以继续他的初始化方式:

 HttpMethodName(ProtocolOperation... ops) {
    this.ops = Collections.unmodifiableList(Arrays.asList(ops));
 }