繁体   English   中英

枚举在Java中实现不同的方法

[英]Enums to implement different methods in Java

假设我构建了以下类

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的技巧?

谢谢

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

我想出了一些更好的

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

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

也许尝试类似的东西:

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM