Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 枚举和字典之间的交叉_Java_Data Structures - Fatal编程技术网

Java 枚举和字典之间的交叉

Java 枚举和字典之间的交叉,java,data-structures,Java,Data Structures,在我的Java项目中,我需要处理一些字符串(一次大约10-30个)。我想要一个数据结构来保存它们,其属性如下: 可以为每个字符串指定唯一的名称 唯一的名称可以像变量一样在代码中使用,支持IDE自动完成,不调用getValue()或toString()等 可以迭代数据结构中的每个值 实际上,我希望代码看起来像这样: MagicalDataStructure<String> mds = new MagicalDataStructure( FirstString = "foo

在我的Java项目中,我需要处理一些字符串(一次大约10-30个)。我想要一个数据结构来保存它们,其属性如下:

  • 可以为每个字符串指定唯一的名称
  • 唯一的名称可以像变量一样在代码中使用,支持IDE自动完成,不调用getValue()或toString()等
  • 可以迭代数据结构中的每个值
  • 实际上,我希望代码看起来像这样:

    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);
    
                }   
            }