将范围值用作地图中的关键字

时间:2017-08-24 16:17:12

标签: java maps range

假设我希望我的应用程序根据某些标准确定用户的健康水平。

标准可能是这样的:年龄,正在服用药物?,400米跑

起初我虽然可以创建一个Map,其中值是适应度级别,而键是一个具有所有条件的对象,但由于条件是范围,因此不起作用。

例如: 如果年龄在18到22之间且onMedication = false且run400m = [70,80]

健康水平=好

现在,如果只有一个参数在不同的范围内,则适应度水平会有所不同。我怎么能做到这一点?

3 个答案:

答案 0 :(得分:1)

您可以使用TreeMap类。有非常有用的方法来处理键值范围。例如:

    TreeMap<Integer, String> myTreeMap = new TreeMap<>();

    myTreeMap.put(10, "A");
    myTreeMap.put(20, "B");
    myTreeMap.put(30, "C");
    myTreeMap.put(40, "D");

    System.out.println(myTreeMap.floorEntry(25));   

将打印第二个选项(20 = B)。我建议您检查TreeMap及其所有方法。

答案 1 :(得分:1)

也许您可以使用OOP并执行以下操作:

public class FitnessApp {
    public static void main(String[] args) {
        Map<String, Object> params = new HashMap<>();
        params.put("age", 17);
        params.put("onMedication", false);
        System.out.printf(new FitnessLevelCalculator().calculateFor(params).name());
    }
}

class FitnessLevelCalculator {
    private LinkedList<FitnessLevel> fitnessLevels = new LinkedList<>();

    public FitnessLevelCalculator() {
        fitnessLevels.add(new FitnessLevel(FitnessLevelEnum.ATHLETIC, Arrays.asList(new RangeCriteria("age", 18, 25), new BooleanCriteria("onMedication", false))));
        fitnessLevels.add(new FitnessLevel(FitnessLevelEnum.GOOD, Arrays.asList(new RangeCriteria("age", 14, 17), new BooleanCriteria("onMedication", false))));
        fitnessLevels.add(new FitnessLevel(FitnessLevelEnum.ILL, Arrays.asList(new RangeCriteria("age", 16, 17))));
    }

    public FitnessLevelEnum calculateFor(Map<String, Object> params) {
        ListIterator<FitnessLevel> listIterator = fitnessLevels.listIterator();
        while (listIterator.hasNext()) {
            FitnessLevel fitnessLevel = listIterator.next();
            if (fitnessLevel.accept(params)) {
                return fitnessLevel.getLevel();
            }
        }

        return FitnessLevelEnum.NOT_CLASSIFIED;
    }
}

enum FitnessLevelEnum {
    ILL, GOOD, ATHLETIC, NOT_CLASSIFIED
}

class FitnessLevel {
    private List<Criteria> criteriaList = new ArrayList<>();
    private FitnessLevelEnum level;

    public FitnessLevel(FitnessLevelEnum level, List<Criteria> criteriaList) {
        this.criteriaList = criteriaList;
        this.level = level;
    }

    public boolean accept(Map<String, Object> params) {
        for (Criteria criteria : criteriaList) {
            if (!params.containsKey(criteria.getName())) {
                return false;
            }
            if (!criteria.satisfies(params.get(criteria.getName()))) {
                return false;
            }
        }
        return true;
    }

    public FitnessLevelEnum getLevel() {
        return level;
    }
}

abstract class Criteria<T> {
    private String name;

    public Criteria(String name) {
        this.name = name;
    }

    public abstract boolean satisfies(T param);

    public String getName() {
        return name;
    }
}

class RangeCriteria extends Criteria<Integer> {
    private int min;
    private int max;

    public RangeCriteria(String name, int min, int max) {
        super(name);
        this.min = min;
        this.max = max;
    }

    @Override
    public boolean satisfies(Integer param) {
        return param >= min && param <= max;
    }
}

class BooleanCriteria extends Criteria<Boolean> {
    private Boolean expectedValue;

    public BooleanCriteria(String name, Boolean expectedValue) {
        super(name);
        this.expectedValue = expectedValue;
    }

    @Override
    public boolean satisfies(Boolean param) {
        return param == expectedValue;
    }
}

答案 2 :(得分:0)

在您的具体情况下,我认为在Map中使用键是不好的。可能有一种方法可以将具有所有条件的Object作为您的业务,但它非常复杂且不值得这样做。 Interpreter Pattern可能对此有所帮助。

希望得到这个帮助。