private double getEvaluation(FastByIDMap <PreferenceArray> testPrefs, Recommender recommender)
        {
            this.reset();
            List <Action> callables         = new List <Action>();
            AtomicInteger noEstimateCounter = new AtomicInteger();

            using (IEnumerator <KeyValuePair <long, PreferenceArray> > enumerator = testPrefs.entrySet().GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    Action item = null;
                    KeyValuePair <long, PreferenceArray> entry = enumerator.Current;
                    if (item == null)
                    {
                        item = delegate
                        {
                            long            userID = entry.Key;
                            PreferenceArray array  = entry.Value;
                            foreach (Preference preference in array)
                            {
                                float f = float.NaN;
                                try
                                {
                                    f = recommender.estimatePreference(userID, preference.getItemID());
                                }
                                catch (NoSuchUserException)
                                {
                                    log.info("User exists in test data but not training data: {}", new object[] { userID });
                                }
                                catch (NoSuchItemException)
                                {
                                    log.info("Item exists in test data but not training data: {}", new object[] { preference.getItemID() });
                                }
                                if (float.IsNaN(f))
                                {
                                    noEstimateCounter.incrementAndGet();
                                }
                                else
                                {
                                    f = this.capEstimatedPreference(f);
                                    this.processOneEstimate(f, preference);
                                }
                            }
                        };
                    }
                    callables.Add(item);
                }
            }
            log.info("Beginning evaluation of {} users", new object[] { callables.Count });
            RunningAverageAndStdDev timing = new FullRunningAverageAndStdDev();

            execute(callables, noEstimateCounter, timing);
            return(this.computeFinalEvaluation());
        }