2017-08-24 60 views
1

假设我希望我的应用程序根据某些条件确定用户的健康水平。使用范围值作为地图中的键

的标准可能是这样的:年龄,目前服用药物?400m跑

起初,我以为我可以创建一个地图,其中值是健身水平,关键是拥有所有的对象标准,但由于标准是范围,这是行不通的。

例如: 如果年龄是18岁和22以及onMedication =假和run400m = [70,80]

健身水平之间= GOOD

现在,如果只有参数之一是在一个不同的范围的健身水平会有所不同。我怎么能做到这一点?

回答

0

在你的具体情况下,我认为它不适合用作Map中的一个键。可能有一种方法可以将对象与所有条件放在一起作为您的业务,但这很复杂,不值得这样做。 Interpreter Pattern可能会帮助你。

希望得到这个帮助。

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及其所有方法。

+0

这正常工作与这种情况下,但如果我有多个远程参数每一个仅是部分关键在地图的价值? – bez

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; 
    } 
} 
+0

这很好,但对我所需要的东西有点矫枉过正。我想我可以根据用户参数建立一个字符串键,并使用它来映射到地图中对应的FitnessLevel。 – bez