Représenter une liste de contrôle avec un score avec une classe Java
J'ai une liste d'éléments, représentée comme une classe Java.
Par exemple
public class CheckList {
private boolean firstItem;
private boolean secondItem;
private boolean thirdItem;
public boolean isFirstItem() { return firstItem; }
public void setFirstItem(boolean firstItem) { this.firstItem = firstItem; }
public boolean isSecondItem() { return secondItem; }
public void setSecondItem(boolean secondItem) { this.secondItem = secondItem; }
public boolean isThirdItem() { return thirdItem; }
public void setThirdItem(boolean thirdItem) { this.thirdItem = thirdItem; }
}
Maintenant, je veux "calculer" un score (pourcentage) du nombre d'éléments d'une liste de contrôle vérifiés. Ma façon naïve de le faire serait la méthode suivante.
private static final int NR_OF_ITEMS = 3;
public double getScore() {
double score = 0;
if (firstItem) { score += 1; }
if (secondItem) { score += 1; }
if (thirdItem) { score += 1; }
return score / NR_OF_ITEMS;
}
Ce n'est cependant pas pratique et semble bizarre (surtout si la liste de contrôle s'allonge). Une autre approche pourrait être d'avoir une liste d'éléments qui pourraient être itérés mais cela signifie ne pas limiter les éléments qui facilement et il a aussi des défauts.
Quelle pourrait être une bonne solution pour représenter une liste de contrôle avec Java? Merci pour vos idées.
1 answers
, j'irais avec votre deuxième approche, c'est à dire utiliser une liste d'éléments. Limiter la quantité d'éléments serait facile si vous enveloppiez la liste dans une autre classe et vérifiez la taille de la liste lors de l'insertion.
Exemple:
class Item {
boolean checked;
String name;
}
class CheckList {
private final int maxItemsAllowed;
private final List<Item> items;
public CheckList( int maxItems ) {
maxItemsAllowed = maxItems;
items = new ArrayList<>( maxItemsAllowed );
}
public void addItem( Item i ) {
if( items.size() >= maxItemsAllowed ) {
throw new IllegalArgumentException("Maximum no. of allowed items (" + maxItemsAllowed + ") exeeded");
}
items.add( i );
}
}
À quels autres "défauts" pensiez-vous?
Mise à JOUR:
Pour limiter le nombre d'éléments possibles, vous pouvez faire Item
une énumération et/ou ne pas fournir de méthodes publiques pour manipuler la liste des itmes.
Afin de traiter avec les doublons, utilisez un Set<Item>
et selon la façon dont vous souhaitez contrôler l'ordre des éléments, un TreeSet
avec un Comparator
approprié ou un LinkedHashSet
avec une vérification de taille modifiée.
Une autre approche pourrait être d'utiliser un Map<Item, Boolean>
et de stocker le drapeau en dehors de l'élément.
Exemple:
enum Item {
ITEM_1("Item no. 1"),
ITEM_2("A second item");
private final String name;
private Item( String name ) {
this.name = name;
}
public String getName() { return name; }
}
class CheckList {
private final int maxItemsAllowed;
private final Map<Item, Boolean> items; //make this a TreeMap or LinkedHashMap
//Constructor and other methods omitted for clarity
public void check(Item item, boolean checked ) {
if( !items.containsKey( item ) ) {
throw new IllegalArgumentException("unknown item");
}
items.put(item, checked); //note the autoboxing here
}
public double getScore() {
int countChecked = 0;
int countTotal = 0; //see explanation below
for( Boolean b : items.values() ) {
if( Boolean.TRUE.equals( b ) {
countChecked++;
}
countTotal++;
}
return (double)countChecked/countTotal;
}
}
Alors pourquoi y a-t-il un countTotal
dans la méthode getScore()
? Étant donné qu'une carte autorise des valeurs null en fonction de votre implémentation et de votre utilisation de la liste de contrôle, il se peut que l'indicateur (valeur) soit null pour un élément dans la liste. Si c'est le cas et que null
ne signifie pas false
vous pouvez simplement vérifier b != null
et incrémenter seulement countTotal
si cela est vrai, c'est-à-dire que ce serait le nombre d'éléments non nuls.