2017-08-24 3 views
1

Disons que je souhaite que mon application détermine le niveau de condition physique de l'utilisateur en fonction de certains critères.Utilisation de valeurs de plage en tant que clé dans une carte

Les critères pourraient être quelque chose comme: l'âge, actuellement prendre des médicaments ?, 400 m course

Au début, je pensais que je pouvais créer une carte où la valeur est le niveau de condition physique et la clé est un objet qui a toutes les critères, mais comme les critères sont des fourchettes, cela ne fonctionnerait pas.

Par exemple: si l'âge est compris entre 18 et 22 et onMedication = false et run400m = [70, 80]

condition physique = BON

Maintenant, si seulement l'un des paramètres est dans un autre varier le niveau de forme physique serait différent. Comment pourrais-je y parvenir?

Répondre

0

Dans votre cas spécifique, je ne pense pas qu'il soit bon d'utiliser comme une clé dans Map. Il y a peut-être un moyen de mettre l'Objet dans toutes les conditions, mais c'est assez complexe et ça ne vaut pas la peine. Le Interpreter Pattern peut vous aider à ce sujet.

Espérons cette aide.

1

Vous pouvez utiliser une classe TreeMap pour cela. Il existe des méthodes très utiles pour gérer les plages de valeurs clés. Par exemple:

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

Sera imprimé la deuxième option (20 = B). Je vous recommande de vérifier la TreeMap et toutes ses méthodes pour ce cas.

+0

Cela fonctionne très bien avec ce scénario, mais si j'ai plusieurs rangeai paramètres dont chacun est seulement une clé partielle à la valeur de la carte? – bez

1

Peut-être que vous pouvez utiliser POO et faire quelque chose comme ceci:

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

C'est sympa mais un peu exagéré pour ce dont j'ai besoin. Je pense que je peux juste construire une clé de chaîne basée sur les paramètres utilisateur et l'utiliser pour mapper au FitnessLevel correspondant dans la carte . – bez