public BigDecimal computeSimilarity(Integer firstUserId, Integer secondUserId) {
        BigDecimal result = new BigDecimal(0.0);

        Integer firstUserIndex = ratingsTable.getUserIds().indexOf(firstUserId);
        Integer secondUserIndex = ratingsTable.getUserIds().indexOf(secondUserId);

        UserRatingsList firstUserRatings = ratingsTable.getRatingsByUserId(firstUserId);
        UserRatingsList secondUserRatings = ratingsTable.getRatingsByUserId(secondUserId);

        Map<Integer, BigDecimal> firstUserRatingsMap = firstUserRatings.getRatingsMap();
        Map<Integer, BigDecimal> secondUserRatingsMap = secondUserRatings.getRatingsMap();

        int count = 0;
        BigDecimal firstMeanRating = new BigDecimal(0.0);
        BigDecimal secondMeanRating = new BigDecimal(0.0);
        for (Integer movieIndex : firstUserRatingsMap.keySet()) {
            if (secondUserRatingsMap.containsKey(movieIndex)) {
                count++;
                firstMeanRating = firstMeanRating.add(firstUserRatingsMap.get(movieIndex), new MathContext(11));
                secondMeanRating = secondMeanRating.add(secondUserRatingsMap.get(movieIndex), new MathContext(11));
            }
        }

        firstMeanRating = firstMeanRating.divide(new BigDecimal(count), new MathContext(11));
        secondMeanRating = secondMeanRating.divide(new BigDecimal(count), new MathContext(11));

        meanRatings.put(firstUserIndex, firstMeanRating);
        meanRatings.put(secondUserIndex, secondMeanRating);

        BigDecimal firstLength = new BigDecimal(0.0);
        BigDecimal secondLength = new BigDecimal(0.0);

        meanRatings.put(firstUserIndex, firstMeanRating);
        meanRatings.put(secondUserIndex, secondMeanRating);

        for (Integer movieIndex : firstUserRatingsMap.keySet()) {
            if (secondUserRatingsMap.containsKey(movieIndex)) {
                BigDecimal intermediateResult = firstUserRatingsMap.get(movieIndex).subtract(meanRatings.get(firstUserIndex),
                                new MathContext(7));
                intermediateResult = intermediateResult.multiply(
                                secondUserRatingsMap.get(movieIndex).subtract(meanRatings.get(secondUserIndex), new MathContext(11)),
                                new MathContext(7));

                BigDecimal intermediateLength = firstUserRatingsMap.get(movieIndex).subtract(meanRatings.get(firstUserIndex),
                                new MathContext(7));
                firstLength = firstLength.add(intermediateLength.pow(2));
                intermediateLength = secondUserRatingsMap.get(movieIndex).subtract(meanRatings.get(secondUserIndex), new MathContext(11));
                secondLength = secondLength.add(intermediateLength.pow(2));
                result = result.add(intermediateResult, new MathContext(11));
            }
        }

        userRatingLengths.put(firstUserIndex, new BigDecimal(Math.sqrt(firstLength.doubleValue()), new MathContext(11)));
        userRatingLengths.put(secondUserIndex, new BigDecimal(Math.sqrt(secondLength.doubleValue()), new MathContext(11)));

        result = result.divide(userRatingLengths.get(firstUserIndex), new MathContext(11));
        result = result.divide(userRatingLengths.get(secondUserIndex), new MathContext(7));

        return result;
    }