fdomig
fdomig

Reputation: 4457

Represent a checklist with a score with a Java class

I have a checklist of items, represented as a Java class.

E.g.

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

Now I want to "calculate" a score (percentage) of how many items in a checklist are checked. My naïve way of doing that would be the following method.

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

This is however somehow unpractical and seems to be weird (especially if the checklist gets longer). Another approach could be to have a list of items which could be iterated over but this does mean cannot limit the items that easily and it also has it flaws.

What could be a good solution to represent a checklist with Java? Thank you for your ideas.

Upvotes: 0

Views: 331

Answers (1)

Thomas
Thomas

Reputation: 88747

I'd go with your second approach, i.e. use a list of items. Limiting the amount of items would be easy if you wrapped the list in another class and check the size of the list upon inserting.

Example:

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

What other "flaws" were you thinking of?

UPDATE:

For limiting the number of possible items, you could make Item an enum and/or don't provide public methods to manipulate the list of itmes.

In order to deal with duplicates, use a Set<Item> and depending on how you want to control the order of items either a TreeSet with an appropriate Comparator or a LinkedHashSet with a modified size check.

Another approach could be to use a Map<Item, Boolean> and store the flag outside the item.

Example:

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

So why is there a countTotal in the getScore() method? Since a map allows null values depending on your implementation and usage of the checklist, there might the flag (value) might be null for an item in the list. If this is the case and null doesn't mean false you could just check b != null and only increment countTotal if that is true, i.e. it would be the number of non-null items.

Upvotes: 1

Related Questions