Java 枚举和字典之间的交叉
在我的Java项目中,我需要处理一些字符串(一次大约10-30个)。我想要一个数据结构来保存它们,其属性如下:Java 枚举和字典之间的交叉,java,data-structures,Java,Data Structures,在我的Java项目中,我需要处理一些字符串(一次大约10-30个)。我想要一个数据结构来保存它们,其属性如下: 可以为每个字符串指定唯一的名称 唯一的名称可以像变量一样在代码中使用,支持IDE自动完成,不调用getValue()或toString()等 可以迭代数据结构中的每个值 实际上,我希望代码看起来像这样: MagicalDataStructure<String> mds = new MagicalDataStructure( FirstString = "foo
MagicalDataStructure<String> mds = new MagicalDataStructure(
FirstString = "foo",
SecondString = "bar",
);
/*
This section would output:
foo
bar
*/
for (String value : mds) {
System.out.println(value);
}
/*
This section would output:
The first value is: foo
*/
System.out.println("The first value is: " + FirstString);
MagicalDataStructure mds=新MagicalDataStructure(
FirstString=“foo”,
SecondString=“bar”,
);
/*
本节将输出:
福
酒吧
*/
for(字符串值:mds){
系统输出打印项次(值);
}
/*
本节将输出:
第一个值是:foo
*/
System.out.println(“第一个值是:“+FirstString”);
我考虑过的事情:
- 一个充满静态期末考试的班级。这满足了#1和#2,但我不能重复它们——至少不能不借助黑暗魔咒反射
- 一本字典。这满足#1和#3,但键不会自动完成,并且在访问值时还涉及其他语法
- 枚举。这也解决了#1和#3,但是访问字符串值需要一点额外的代码
是否有数据结构、库等可以满足我的要求?如果字符串是您可能想要使用的属性,或者。这可以用来解决问题1/3。
要解决问题2,您可以创建作为HashMap键的枚举,这样您就需要编写HashMap.get(枚举),它将自动完成所有操作。此解决方案添加了文字,但从自动完成中获益。我绝对喜欢这方面的地图:
public enum PagePath {
PATH1,
PATH2,
// etc.
}
public static final Map<PagePath, String> ALL_PATHS;
static {
Map<PagePath, String> paths = new EnumMap<>(PagePath.class);
paths.put(PagePath.PATH1, "/html/div[0]/h1");
paths.put(PagePath.PATH2, "/html//form/input[id='firstname']");
// etc.
// Make sure no one breaks things by removing entries
// or by adding enum constants while forgetting to account
// for them in the above Map.
if (!paths.keySet().equals(EnumSet.allOf(PagePath.class))) {
throw new RuntimeException(
"Map does not have entries for all PagePath constants!");
}
ALL_PATHS = Collections.unmodifiableMap(paths);
}
公共枚举页面路径{
路径1,
路径2,
//等等。
}
公共静态最终映射所有路径;
静止的{
映射路径=新的EnumMap(PagePath.class);
path.put(PagePath.PATH1,“/html/div[0]/h1”);
put(PagePath.PATH2,“/html//form/input[id='firstname']”);
//等等。
//确保没有人通过删除条目来破坏东西
//或者通过添加枚举常量而忘记计算
//在上面的地图上。
如果(!path.keySet().equals(EnumSet.allOf(PagePath.class))){
抛出新的运行时异常(
“映射没有所有PagePath常量的条目!”);
}
所有路径=集合。不可修改映射(路径);
}
正如您所提到的,另一种可能性是使用字符串常量。您可以将这些常量的初始化放在“所有值”列表的初始化中,以确保不会忘记它们:
public static final String PATH1;
public static final String PATH2;
// etc.
public static final Collection<String> ALL_PATHS;
static {
ALL_PATHS = Collections.unmodifiableCollection(Arrays.asList(
PATH1 = "/html/div[0]/h1",
PATH2 = "/html//form/input[id='firstname']",
// etc.
));
}
公共静态最终字符串路径1;
公共静态最终字符串路径2;
//等等。
公共静态最终集合所有_路径;
静止的{
所有路径=集合。不可修改的集合(Arrays.asList(
PATH1=“/html/div[0]/h1”,
PATH2=“/html//form/input[id='firstname']”,
//等等。
));
}
如果有人删除常量,他们将被迫从Arrays.asList调用中删除其初始化。如果有人添加了一个常量,并使其与其他常量的声明保持一致,他们将被迫将其添加到“所有路径”列表中,因为如果不这样做,将意味着它永远不会初始化,编译器将捕获该常量。您可以编写一个自定义方法,使用enum返回字符串值吗
public enum MagicalDataStructure {
FirstString("foo"),
SecondString("bar");
String value;
MagicalDataStructure(String value) {
this.value = value;
}
public static List<String> getMagicalStrings() {
List<String> strings = new ArrayList<String>();
for (MagicalDataStructure item : MagicalDataStructure.values()) {
strings.add(item.value);
}
return strings;
}
}
我们使用EnumMap作为CustomEnumMap的基础。我的理解是,您不需要put方法,所以我们的第一个任务是为它们实际抛出不支持的操作。第二步是用实际表示的值定义不同的枚举。第三步是通过将任何枚举转换为CustomEnumMap的静态方法实现的。以后如何使用地图,您可以自己查看
不过还有一个地方需要改进,那就是静态方法的实现。不幸的是,我只是在学习Java8Lambdas,所以我不能以一种好的方式快速实现它。但我将对此进行研究,稍后将为您提供此方法的最终实现。或者是有人想帮我,欢迎
public static class CustomEnumMap<K extends Enum<K>,V> extends EnumMap<K, V> {
public CustomEnumMap(EnumMap<K, ? extends V> m) {
super(m);
}
@Override
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}
}
public static enum EnumA {
FIRST("value1"),SECOND("value2"),THREE("value3");
private String value;
private EnumA(String value) {
this.value = value;
}
public String toString() {
return value;
}
}
public static enum EnumB {
FIRST("value1"),SECOND("value2");
private String value;
private EnumB(String value) {
this.value = value;
}
public String toString() {
return value;
}
}
public static <T extends Enum<T>> CustomEnumMap<T, String> toMap(T[] myenum) {
return new CustomEnumMap<T,String>(new EnumMap<T,String>( Arrays.stream(myenum).collect(Collectors.toMap(t->(T)t, t->t.toString()))));
}
public static void main(String args[]) {
CustomEnumMap<EnumA, String> enumA = toMap(EnumA.values());
CustomEnumMap<EnumA, String> enumB = toMap(EnumA.values());
for (String stringA : enumA.values()) {
System.out.print(stringA);
}
System.out.println("");
for (String stringB : enumB.values()) {
System.out.print(stringB);
}
}
公共静态类CustomEnumMap扩展了EnumMap{
公共CustomEnumMap(EnumMap m){
超级(m);
}
@凌驾
公共V输入(K键,V值){
抛出新的UnsupportedOperationException();
}
@凌驾
public void putAll(映射您可以重写toString()
在枚举中——但在我看来这很难看。枚举似乎是最合适的。为什么你不能迭代静态最终值?是什么阻止你声明一个也包含这些值的数组?嗯,字符串代表什么?它们是用户输入的吗?对于唯一的名称,如何计算唯一的名称?请注意,一个字符串有上百个唯一的名称,除非名称必须具有最大长度,否则不可能有真正唯一的名称。字符串是常量,在编译时之前定义。在这种特殊情况下,它们是Selenium WebElements的xpath字符串。我希望能够单独使用它们(与WebElements交互)和作为一个组(验证所有元素是否存在)。
public static class CustomEnumMap<K extends Enum<K>,V> extends EnumMap<K, V> {
public CustomEnumMap(EnumMap<K, ? extends V> m) {
super(m);
}
@Override
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}
}
public static enum EnumA {
FIRST("value1"),SECOND("value2"),THREE("value3");
private String value;
private EnumA(String value) {
this.value = value;
}
public String toString() {
return value;
}
}
public static enum EnumB {
FIRST("value1"),SECOND("value2");
private String value;
private EnumB(String value) {
this.value = value;
}
public String toString() {
return value;
}
}
public static <T extends Enum<T>> CustomEnumMap<T, String> toMap(T[] myenum) {
return new CustomEnumMap<T,String>(new EnumMap<T,String>( Arrays.stream(myenum).collect(Collectors.toMap(t->(T)t, t->t.toString()))));
}
public static void main(String args[]) {
CustomEnumMap<EnumA, String> enumA = toMap(EnumA.values());
CustomEnumMap<EnumA, String> enumB = toMap(EnumA.values());
for (String stringA : enumA.values()) {
System.out.print(stringA);
}
System.out.println("");
for (String stringB : enumB.values()) {
System.out.print(stringB);
}
}