基于枚举的Java表格/矩阵

Hub*_*iak 6 java enums matrix

我有两个枚举:level有3个值和criticality4个值.这两个映射的组合映射到priority枚举中的8个值之一.映射是非线性的,将来可能会发生变化.

什么是实现静态函数的最佳*方法,该函数需要级别和关键性并输出优先级?

*最好易于阅读和理解,易于更换,更安全,而不是性能损失.考虑到输入域将来可能发生变化的解决方案的额外分数.

到目前为止我考虑的方式:

嵌套开关..case.许多行和许多样板代码.如果您忘记在案例中返回值,也容易出错.基本上代码看起来像这样:

    switch (bc) {
        case C1:
            switch (el) {
                case E1:
                    return EmergencyPriority.P1;
                case E2:
                    return EmergencyPriority.P2;
                case E3:
                    return EmergencyPriority.P3;
            }
        case C2:
            switch (el) {
                case E1:
                    return EmergencyPriority.P2;
                case E2:
                    return EmergencyPriority.P3;
                case E3:
                    return EmergencyPriority.P4;
            }
        case C3:
            switch (el) {
                case E1:
                    return EmergencyPriority.P4;
                case E2:
                    return EmergencyPriority.P5;
                case E3:
                    return EmergencyPriority.P6;
            }
        case C4:
            switch (el) {
                case E1:
                    return EmergencyPriority.P6;
                case E2:
                    return EmergencyPriority.P7;
                case E3:
                    return EmergencyPriority.P8;
            }
    }
Run Code Online (Sandbox Code Playgroud)

Mutikey Map需要一个外部库,我没有找到一种方法来很好地插入初始值而没有很多函数调用和样板复合键.


if..else if .. else与switch case基本相同,但有更多的样板代码.尽管不那么容易出错.


使用枚举值作为数组索引的整数时的二维数组,如果位置枚举值发生变化,则可能会无声地失败.


您的解决方案

Luk*_*der 7

这种结构可能是存储数据的"最佳"方式("最佳"=我假设您的数据,因为我对您的switch基础解决方案完全没问题)

1.基于EnumMap的解决方案

EnumMap<Level, EnumMap<Criticality, Priority>> map = new EnumMap<>(Level.class);
EnumMap<Criticality, Priority> c1 = new EnumMap<>(Criticality.class);
c1.put(Criticality.E1, Priority.P1);
..
map.put(Level.C1, c1);
...
Run Code Online (Sandbox Code Playgroud)

然后,只需编写此实用程序方法即可访问该结构:

public static Priority priority(Level level, Criticality criticality) {
    return map.get(level).get(criticality);
}
Run Code Online (Sandbox Code Playgroud)

优点EnumMap是:它提供了Map方便,同时效率很高,因为所有可能的密钥都是事先知道的,因此值可以存储在Object[].

2.基于阵列的解决方案

你已经提到了这一点,但我仍然会重复这个想法,因为我过去已经这样做了,并且采用了适当的格式化(当然,绝不能被开发者打破),这种方法非常易读,而且不是很容易出错.

请记住,格式化是关键:

Priority[][] map = {
  //               Criticality.E1   Criticality.E2   Criticality.E3
  // ----------------------------------------------------------------
  /* Level.C1 */ { Priority.P1    , Priority.P2    , Priority.P3    },
  /* Level.C2 */ { Priority.P2    , Priority.P3    , Priority.P4    },
  /* Level.C3 */ { Priority.P3    , Priority.P4    , Priority.P5    },
  /* Level.C4 */ { Priority.P4    , Priority.P5    , Priority.P6    }
};
Run Code Online (Sandbox Code Playgroud)

现在,该方法如下所示:

public static Priority priority(Level level, Criticality criticality) {
    return map[level.ordinal()][criticality.ordinal()];
}
Run Code Online (Sandbox Code Playgroud)

为了防止有人在中间添加新的枚举值而无声地失败,只需添加一个单元测试,断言每个枚举文字的预期序号.同样的测试也可以断言Level.values().lengthCriticality.values().length值,并且您对未来是安全的.


Val*_*tin 1

1. 使用构造函数定义枚举

EnumMap受到using评论的启发Object[],我想出了这个解决方案:

public enum EmergencyPriority {
    P1(BusinessCriticality.C1, EmergencyLevel.E1), 
    P2(BusinessCriticality.C1, EmergencyLevel.E2, 
       BusinessCriticality.C2, EmergencyLevel.E1), 
    P3(BusinessCriticality.C1, EmergencyLevel.E3, 
       BusinessCriticality.C2, EmergencyLevel.E2), 
    P4(BusinessCriticality.C2, EmergencyLevel.E3, 
       BusinessCriticality.C3, EmergencyLevel.E1), 
    P5(BusinessCriticality.C3, EmergencyLevel.E2), 
    P6(BusinessCriticality.C3, EmergencyLevel.E3, 
       BusinessCriticality.C4, EmergencyLevel.E1), 
    P7(BusinessCriticality.C4, EmergencyLevel.E2), 
    P8(BusinessCriticality.C4, EmergencyLevel.E3);

    private static EmergencyPriority[][] PRIORITIES;

    private EmergencyPriority(BusinessCriticality c, EmergencyLevel l) {
        addPriority(l, c, this);
    }

    private EmergencyPriority(BusinessCriticality c, EmergencyLevel l, 
            BusinessCriticality c2, EmergencyLevel l2) {
        addPriority(l, c, this);
        addPriority(l2, c2, this);
    }

    private static void addPriority(EmergencyLevel l, BusinessCriticality c, EmergencyPriority p) {
        if (PRIORITIES == null) {
            PRIORITIES = new EmergencyPriority[EmergencyLevel.values().length][BusinessCriticality.values().length];
        }
        PRIORITIES[l.ordinal()][c.ordinal()] = p;
    }

    public static EmergencyPriority of(BusinessCriticality c, EmergencyLevel l) {
        return PRIORITIES[l.ordinal()][c.ordinal()];
    }
}
Run Code Online (Sandbox Code Playgroud)

2.定义一个枚举并静态初始化对应数组

另一个解决方案是使用一个没有构造函数的简单枚举,并静态初始化优先级数组,这样可以根据您认为适合的可读性对它们进行重新排序:

import static com.package.BusinessCriticality.*;
import static com.package.EmergencyLevel.*;

public enum EmergencyPriority {
    P1, P2, P3, P4, P5, P6, P7, P8;

    private static EmergencyPriority[][] PRIORITIES = new EmergencyPriority[BusinessCriticality.values().length][EmergencyLevel.values().length];

    private void define(BusinessCriticality c, EmergencyLevel e) {
        PRIORITIES[c.ordinal()][e.ordinal()] = this;
    }

    static {
        P1.define(C1, E1);

        P2.define(C1, E2);
        P2.define(C2, E1);

        P3.define(C1, E3);
        P3.define(C2, E2);

        P4.define(C2, E3);
        P4.define(C3, E1);

        P5.define(C3, E2);

        P6.define(C3, E3);
        P6.define(C4, E1);

        P7.define(C4, E2);

        P8.define(C4, E3);
    }

    public static EmergencyPriority of(BusinessCriticality c, EmergencyLevel e) {
        return PRIORITIES[c.ordinal()][e.ordinal()];
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以进行以下 JUnit 测试,以确保 EmergencyPriority 具有所有组合,以防您扩展 BusinessCriticality 或 EmergencyLevel:

@Test
public void testEnumCompletude() {
    for (BusinessCriticality c : BusinessCriticality.values()) {
        for (EmergencyLevel e : EmergencyLevel.values()) {
            assertNotNull(String.format("%s/%s combination was forgotten", c, e), 
                EmergencyPriority.of(c, e));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)