【问题标题】:Enums to implement different methods in Java在 Java 中实现不同方法的枚举
【发布时间】:2019-01-07 00:04:08
【问题描述】:

假设我构造了以下类

public enum OptimizationAlgorithmType {

    VANILLA(new HashMap<String, Double>()) {

        private final static String ETA = "eta";
        private Double eta = null;

        public OptimizationAlgorithmType setEta(Double eta) {
            this.eta = eta;
            return this;
        }

        @Override
        public Map<String, Double> getHyperarameters() {
            this.map.put(ETA, eta);
            return this.map;
        }       
    }, 

    MOMENTUM(new HashMap<String, Double>()) {

        private final static String ALPHA = "alpha";
        private final static String BETA = "beta";

        private Double alpha = null;
        private Double beta = null;

        public OptimizationAlgorithmType setAlpha(Double alpha) {
            this.alpha = alpha;
            return this;
        }

        public OptimizationAlgorithmType setBeta(Double beta) {
            this.beta = beta;
            return this;
        }

        @Override
        public Map<String, Double> getHyperarameters() {
            this.map.put(ALPHA, alpha);
            this.map.put(BETA, beta);
            return this.map;
        }
    };

    protected Map<String, Double> map;

    private OptimizationAlgorithmType(Map<String, Double> map) {
        this.map = map;
    }

    public abstract Map<String, Double> getHyperarameters();    
}

我的目标是构建一个 API,当我选择一个特定的 Enum 时,就会有不同的方法可用。例如

MultiThreadBackpropagation backpropagation = new MultiThreadBackpropagation(feedForward)
        .setNumberThreads(10)
        .setBatch(5)
        .setEpochs(100)
        .setOptimizer(OptimizationAlgorithmType.VANILLA.setEta(0.001));

或者

MultiThreadBackpropagation backpropagation = new MultiThreadBackpropagation(feedForward)
        .setNumberThreads(10)
        .setBatch(5)
        .setEpochs(100)
        .setOptimizer(OptimizationAlgorithmType.MOMENTUM.setAlpha(0.01).setBeta(0.99));

很遗憾,这是不允许的。 ide 会警告未使用的方法(即:setEta()),并且这些方法根本无法从特定的枚举中进行选择。

我可以使用什么技巧来获得所需的 API?

谢谢

编辑在下方添加了替代答案

【问题讨论】:

  • 看起来你真的不应该为此使用枚举。除了您询问的问题之外,您还可变地使用枚举,这是非常可疑的。看来您应该编写一些普通的构建器或其他东西。 (为了记录,这里没有任何技巧可以让它工作。只是不要使用枚举。)
  • @Radiodef 我只是想以某种方式呈现 api - 我可以通过其他方式使其工作。
  • 您可以通过使用公共静态最终字段而不是枚举值以相同的方式为您的客户呈现 API。

标签: java enums


【解决方案1】:

我想出了一些更好的

先是一个接口,然后是实现该接口的两个参数类

public interface Hyperparameter {...}   

public enum VanillaParameter implements Hyperparameter {
        ETA {

            @Override
            public Double getValue() {
                return this.etaValue;
            }

            @Override
            public void setValue(Double value) {

                if (value == null) {
                    throw new IllegalStateException("Parameter value cannot be set to null!");
                }
                this.etaValue = value;
            }
        };
        protected Double etaValue = 0.005;
    }

    public enum MomentumParameter implements Hyperparameter {
    ...
    }

现在添加主枚举类

    public enum OptimizationType {

        VANILLA{
            private VanillaParameter eta = VanillaParameter.ETA;

            @Override
            public Hyperparameter get(Hyperparameter parameter) {
                switch ((VanillaParameter) parameter) {
                case ETA: return this.eta;
                }
                return null;
            }

            @Override
            public OptimizationType set(Hyperparameter parameter, Double value) {

                switch ((VanillaParameter) parameter) {
                case ETA: 
                    this.eta.setValue(value);
                    break;
                }
                return OptimizationType.VANILLA;
            }
        },
        ...
}

在我看来,API 看起来非常不错,并且与我最初的意图很相似。期待建议

MultiThreadBackpropagation backpropagation = new MultiThreadBackpropagation.BackpropagationBuilder(feedForward)
        .setBatch(5)
        .setEpochs(100)
        .setThreads(10)
        .setOptimizer(OptimizationType.MOMENTUM
                .set(MomentumParameter.ALPHA, 0.001)
                .set(MomentumParameter.BETA, 0.92))
        .build();

【讨论】:

  • 每次调用: set(Hyperparameter parameter, Double value) ,你为所有使用 OptimizationType.VANILLA 的人改变 eta 的值
  • @RayTayek 是的,非常正确,非常有问题。
【解决方案2】:

也许可以试试:

import java.util.Arrays;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;

public class So54067082enums_to_implement_different_methods_in_java {
    enum Type {
        vanilla(new TreeSet<>(Arrays.asList(new String[] {"eta"}))),
        momentum(new TreeSet<>(Arrays.asList(new String[] {"alpha","beta"})));
        Type(Set<String> names) {
            this.names=names;

        }
        final Set<String> names;
    }
    static class ParameterSet {
        ParameterSet(Type type) {
            this.type=type;
        }
        Double get(String name) {
            if(type.names.contains(name))
                return map.get(name);
            else throw new RuntimeException("oops");
        }
        void set(String name,Double value) {
            if(type.names.contains(name))
                map.put(name,value);
            else throw new RuntimeException("oops");
        }
        @Override public String toString() {
            return "ParameterSet [type="+type+", map="+map+"]";
        }
        final Type type;
        private final SortedMap<String,Double> map=new TreeMap<>();

    }
    public static void main(String[] args) {
        ParameterSet parameterSet=new ParameterSet(Type.vanilla);
        parameterSet.set("eta",.01);
        System.out.println(parameterSet);
        ParameterSet parameterSet2=new ParameterSet(Type.momentum);
        parameterSet2.set("alpha",.1);
        parameterSet2.set("beta",.9);
        System.out.println(parameterSet2);
    }
}

【讨论】:

    【解决方案3】:

    我不明白你为什么不能用一种不那么天真的方法来解决问题:

    class OptimizationAlgorithm {
      public static class Vanilla implements OptimizationAlgorithm {
        public Vanilla setAlpha(float a) {
          return this;
        }
    
        public Vanilla setBeta(float a) {
          return this;
        }
      }
    
      public static Vanilla vanilla() { return new Vanilla(); }
    }
    
    backpropagation.setOptimizer(OptimizationAlgorithm.vanilla().setAlpha(0.05f).setBeta(0.10f));
    

    样板代码少很多,没有可变静态实例问题,并且从外部看基本相同的界面。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多