@Override
 public void setPreference(long userID, long itemID, float value) throws TasteException {
   DataModel dataModel = getDataModel();
   double prefDelta;
   try {
     Float oldPref = dataModel.getPreferenceValue(userID, itemID);
     prefDelta = oldPref == null ? value : value - oldPref;
   } catch (NoSuchUserException nsee) {
     prefDelta = value;
   }
   super.setPreference(userID, itemID, value);
   try {
     buildAveragesLock.writeLock().lock();
     RunningAverage itemAverage = itemAverages.get(itemID);
     if (itemAverage == null) {
       RunningAverage newItemAverage = new FullRunningAverage();
       newItemAverage.addDatum(prefDelta);
       itemAverages.put(itemID, newItemAverage);
     } else {
       itemAverage.changeDatum(prefDelta);
     }
     RunningAverage userAverage = userAverages.get(userID);
     if (userAverage == null) {
       RunningAverage newUserAveragae = new FullRunningAverage();
       newUserAveragae.addDatum(prefDelta);
       userAverages.put(userID, newUserAveragae);
     } else {
       userAverage.changeDatum(prefDelta);
     }
     overallAveragePrefValue.changeDatum(prefDelta);
   } finally {
     buildAveragesLock.writeLock().unlock();
   }
 }
 @Override
 public float estimatePreference(long userID, long itemID) throws TasteException {
   DataModel dataModel = getDataModel();
   Float actualPref = dataModel.getPreferenceValue(userID, itemID);
   if (actualPref != null) {
     return actualPref;
   }
   return doEstimatePreference(userID, itemID);
 }
 @Override
 public void removePreference(long userID, long itemID) throws TasteException {
   DataModel dataModel = getDataModel();
   Float oldPref = dataModel.getPreferenceValue(userID, itemID);
   super.removePreference(userID, itemID);
   if (oldPref != null) {
     try {
       buildAveragesLock.writeLock().lock();
       RunningAverage itemAverage = itemAverages.get(itemID);
       if (itemAverage == null) {
         throw new IllegalStateException("No preferences exist for item ID: " + itemID);
       }
       itemAverage.removeDatum(oldPref);
       RunningAverage userAverage = userAverages.get(userID);
       if (userAverage == null) {
         throw new IllegalStateException("No preferences exist for user ID: " + userID);
       }
       userAverage.removeDatum(oldPref);
       overallAveragePrefValue.removeDatum(oldPref);
     } finally {
       buildAveragesLock.writeLock().unlock();
     }
   }
 }