RecommenderUtils { public static List<RecommendedItemVO<Integer, Integer>> filterDuplicates( List<RecommendedItemVO<Integer, Integer>> recommendedItems, boolean useAveragePredictionValues) { if (recommendedItems == null || recommendedItems.size() == 0) { return null; } List<RecommendedItemVO<Integer, Integer>> filtered = new ArrayList<RecommendedItemVO<Integer, Integer>>(recommendedItems.size()); if (useAveragePredictionValues) { Map<ItemVO, Tuple<Double, Integer>> predictionValuesPerItem = new HashMap<ItemVO, Tuple<Double, Integer>>(recommendedItems.size()); List<RecommendedItemVO<Integer, Integer>> tmpRecs = new LinkedList<RecommendedItemVO<Integer, Integer>>(); Iterator<RecommendedItemVO<Integer, Integer>> it = recommendedItems.iterator(); while (it.hasNext()) { RecommendedItemVO<Integer, Integer> recItem = it.next(); Tuple<Double, Integer> predictionValues = predictionValuesPerItem.get(recItem.getItem()); if (predictionValues == null) { predictionValues = new Tuple<Double, Integer>(0.0, 0); tmpRecs.add(recItem); } predictionValues.set_1(predictionValues.get_1() + recItem.getPredictionValue()); predictionValues.set_2(predictionValues.get_2() + 1); predictionValuesPerItem.put(recItem.getItem(), predictionValues); } for (RecommendedItemVO<Integer, Integer> recItem : tmpRecs) { Tuple<Double, Integer> cumulativePredictionValues = predictionValuesPerItem.get(recItem.getItem()); if (cumulativePredictionValues.get_2().equals(1)) { filtered.add(recItem); } else { RecommendedItemVO<Integer, Integer> aggregatedRecItem = new RecommendedItemVO<Integer, Integer>( recItem.getId(), recItem.getItem(), round(cumulativePredictionValues.get_1() / (double) cumulativePredictionValues.get_2(), 16), recItem.getRecommendationId(), recItem.getItemAssocId(), recItem.getExplanation() ); filtered.add(aggregatedRecItem); } } return filtered; } else { Set<ItemVO> itemsAlreadySeen = new HashSet<ItemVO>(recommendedItems.size()); Iterator<RecommendedItemVO<Integer, Integer>> it = recommendedItems.iterator(); while (it.hasNext()) { RecommendedItemVO<Integer, Integer> recItem = it.next(); if (itemsAlreadySeen.contains(recItem.getItem())) continue; itemsAlreadySeen.add(recItem.getItem()); filtered.add(recItem); } return filtered; } }  static List<RecommendedItemVO<Integer, Integer>> filterDuplicates(
            List<RecommendedItemVO<Integer, Integer>> recommendedItems, boolean useAveragePredictionValues); static void filterAlreadyActedOn(List<RecommendedItemVO<Integer, Integer>> recommendedItems,
                                            List<ItemVO<Integer, Integer>> itemsActedOn);  }
@Test public void testFilterDuplicates_No_Duplicates() { List<RecommendedItemVO<Integer, Integer>> recommendedItems = new ArrayList<RecommendedItemVO<Integer, Integer>>(); List<RecommendedItemVO<Integer, Integer>> expectedFilteredRecommendedItems, actualFilteredRecommendedItems; recommendedItems.add(rItem1_1); recommendedItems.add(rItem2_1); recommendedItems.add(rItem3_1); recommendedItems.add(rItem4_1); recommendedItems.add(rItem5_1); expectedFilteredRecommendedItems = recommendedItems; actualFilteredRecommendedItems = filterDuplicates(recommendedItems, false); assertTrue(expectedFilteredRecommendedItems.containsAll(actualFilteredRecommendedItems)); }
@Test public void testFilterDuplicates_No_Duplicates2() { List<RecommendedItemVO<Integer, Integer>> recommendedItems = new ArrayList<RecommendedItemVO<Integer, Integer>>(); List<RecommendedItemVO<Integer, Integer>> expectedFilteredRecommendedItems, actualFilteredRecommendedItems; recommendedItems.add(rItem1_1); recommendedItems.add(rItem2_1); recommendedItems.add(rItem3_1); recommendedItems.add(rItem4_1); recommendedItems.add(rItem5_1); expectedFilteredRecommendedItems = recommendedItems; actualFilteredRecommendedItems = filterDuplicates(recommendedItems, true); assertTrue(expectedFilteredRecommendedItems.containsAll(actualFilteredRecommendedItems)); }
@Test public void testFilterDuplicates_Some_Duplicates_No_Averages() { List<RecommendedItemVO<Integer, Integer>> recommendedItems = new ArrayList<RecommendedItemVO<Integer, Integer>>(); List<RecommendedItemVO<Integer, Integer>> expectedFilteredRecommendedItems, actualFilteredRecommendedItems; recommendedItems.add(rItem1_1); recommendedItems.add(rItem1_2); recommendedItems.add(rItem1_3); recommendedItems.add(rItem2_1); recommendedItems.add(rItem2_2); recommendedItems.add(rItem3_1); recommendedItems.add(rItem4_1); recommendedItems.add(rItem5_1); expectedFilteredRecommendedItems = new ArrayList<RecommendedItemVO<Integer, Integer>>(); expectedFilteredRecommendedItems.add(rItem1_1); expectedFilteredRecommendedItems.add(rItem2_1); expectedFilteredRecommendedItems.add(rItem3_1); expectedFilteredRecommendedItems.add(rItem4_1); expectedFilteredRecommendedItems.add(rItem5_1); actualFilteredRecommendedItems = filterDuplicates(recommendedItems, false); assertTrue(expectedFilteredRecommendedItems.containsAll(actualFilteredRecommendedItems)); }
@Test public void testFilterDuplicates_Some_Duplicates_Use_Averages() { List<RecommendedItemVO<Integer, Integer>> recommendedItems = new ArrayList<RecommendedItemVO<Integer, Integer>>(); List<RecommendedItemVO<Integer, Integer>> expectedFilteredRecommendedItems, actualFilteredRecommendedItems; recommendedItems.add(rItem1_1); recommendedItems.add(rItem1_2); recommendedItems.add(rItem1_3); recommendedItems.add(rItem2_1); recommendedItems.add(rItem2_2); recommendedItems.add(rItem3_1); recommendedItems.add(rItem4_1); recommendedItems.add(rItem5_1); expectedFilteredRecommendedItems = new ArrayList<RecommendedItemVO<Integer, Integer>>(); expectedFilteredRecommendedItems.add(rItem1_avg123); expectedFilteredRecommendedItems.add(rItem2_avg12); expectedFilteredRecommendedItems.add(rItem3_1); expectedFilteredRecommendedItems.add(rItem4_1); expectedFilteredRecommendedItems.add(rItem5_1); actualFilteredRecommendedItems = filterDuplicates(recommendedItems, true); StringBuilder msg = new StringBuilder("expected: "); msg.append(expectedFilteredRecommendedItems); msg.append(", actual: "); msg.append(actualFilteredRecommendedItems); assertTrue(msg.toString(), expectedFilteredRecommendedItems.containsAll(actualFilteredRecommendedItems)); }
@Test public void testFilterDuplicates_All_Duplicates_No_Averages() { List<RecommendedItemVO<Integer, Integer>> recommendedItems = new ArrayList<RecommendedItemVO<Integer, Integer>>(); List<RecommendedItemVO<Integer, Integer>> expectedFilteredRecommendedItems, actualFilteredRecommendedItems; recommendedItems.add(rItem1_1); recommendedItems.add(rItem1_2); recommendedItems.add(rItem1_3); recommendedItems.add(rItem2_1); recommendedItems.add(rItem2_2); recommendedItems.add(rItem2_3); recommendedItems.add(rItem3_1); recommendedItems.add(rItem3_2); recommendedItems.add(rItem3_3); recommendedItems.add(rItem4_1); recommendedItems.add(rItem4_2); recommendedItems.add(rItem4_3); recommendedItems.add(rItem5_1); recommendedItems.add(rItem5_2); recommendedItems.add(rItem5_3); expectedFilteredRecommendedItems = new ArrayList<RecommendedItemVO<Integer, Integer>>(); expectedFilteredRecommendedItems.add(rItem1_1); expectedFilteredRecommendedItems.add(rItem2_1); expectedFilteredRecommendedItems.add(rItem3_1); expectedFilteredRecommendedItems.add(rItem4_1); expectedFilteredRecommendedItems.add(rItem5_1); actualFilteredRecommendedItems = filterDuplicates(recommendedItems, false); assertTrue(expectedFilteredRecommendedItems.containsAll(actualFilteredRecommendedItems)); }
@Test public void testFilterDuplicates_All_Duplicates_Use_Averages() { List<RecommendedItemVO<Integer, Integer>> recommendedItems = new ArrayList<RecommendedItemVO<Integer, Integer>>(); List<RecommendedItemVO<Integer, Integer>> expectedFilteredRecommendedItems, actualFilteredRecommendedItems; recommendedItems.add(rItem1_1); recommendedItems.add(rItem1_2); recommendedItems.add(rItem1_3); recommendedItems.add(rItem2_1); recommendedItems.add(rItem2_2); recommendedItems.add(rItem2_3); recommendedItems.add(rItem3_1); recommendedItems.add(rItem3_2); recommendedItems.add(rItem3_3); recommendedItems.add(rItem4_1); recommendedItems.add(rItem4_2); recommendedItems.add(rItem4_3); recommendedItems.add(rItem5_1); recommendedItems.add(rItem5_2); recommendedItems.add(rItem5_3); expectedFilteredRecommendedItems = new ArrayList<RecommendedItemVO<Integer, Integer>>(); expectedFilteredRecommendedItems.add(rItem1_avg123); expectedFilteredRecommendedItems.add(rItem2_avg123); expectedFilteredRecommendedItems.add(rItem3_avg123); expectedFilteredRecommendedItems.add(rItem4_avg123); expectedFilteredRecommendedItems.add(rItem5_avg123); actualFilteredRecommendedItems = filterDuplicates(recommendedItems, true); StringBuilder msg = new StringBuilder("expected: "); msg.append(expectedFilteredRecommendedItems); msg.append(", actual: "); msg.append(actualFilteredRecommendedItems); assertTrue(msg.toString(), expectedFilteredRecommendedItems.containsAll(actualFilteredRecommendedItems)); }
@Test @Ignore public void testFilterDuplicatesPerformance(){ List<RecommendedItemVO<Integer, Integer>> recItems = generateRecommendedItems1ToNNoDuplicates(1000); List<RecommendedItemVO<Integer, Integer>> recItemsWithDuplicates = generateRecommendedItems1ToNWithDuplicates(1000,200); Stopwatch sw = new Stopwatch(); sw.start(); for (int i = 0; i < 1000; i++) { RecommenderUtils.filterDuplicates(recItems, false); } System.out.println("time for 1000 filtering steps (no duplicates, average:false): " + sw.stop()); sw.start(); for (int i = 0; i < 1000; i++) { RecommenderUtils.filterDuplicates(recItems, true); } System.out.println("time for 1000 filtering steps (no duplicates, average:true): " + sw.stop()); sw.start(); for (int i = 0; i < 1000; i++) { RecommenderUtils.filterDuplicates(recItemsWithDuplicates, false); } System.out.println("time for 1000 filtering steps (with duplicates, average:false): " + sw.stop()); sw.start(); for (int i = 0; i < 1000; i++) { RecommenderUtils.filterDuplicates(recItemsWithDuplicates, true); } System.out.println("time for 1000 filtering steps (with duplicates, average:true): " + sw.stop()); }