public static < E > double optimizedDotProduct ( Counter < E > c1 , Counter < E > c2 ) { double dotProd = 0.0 ; int size1 = c1 . size ( ) ; int size2 = c2 . size ( ) ; if ( size1 < size2 ) { for ( E key : c1 . keySet ( ) ) { double count1 = c1 . getCount ( key ) ; if ( count1 != 0.0 ) { double count2 = c2 . getCount ( key ) ; if ( count2 != 0.0 ) dotProd += ( count1 * count2 ) ; } } } else { for ( E key : c2 . keySet ( ) ) { double count2 = c2 . getCount ( key ) ; if ( count2 != 0.0 ) { double count1 = c1 . getCount ( key ) ; if ( count1 != 0.0 ) dotProd += ( count1 * count2 ) ; } } } return dotProd ; }
This method does not check entries for NAN or INFINITY values in the doubles returned . It also only iterates over the counter with the smallest number of keys to help speed up computation . Pair this method with normalizing your counters before hand and you have a reasonably quick implementation of cosine .