public static <T> float CosineSimilarity(Collection<T> c1, Collection<T> c2) {
		final float matchValue = 1.0f;
		final float missValue = 0.0f;

		Set<T> values = new HashSet<T>(c1.size());
		values.addAll(c1);
		values.addAll(c2);

		float numerator = 0.0f;
		float aSquaredSum = 0.0f;
		float bSquaredSum = 0.0f;

		for (T value : values) {
			float c1Value = missValue;
			float c2Value = missValue;

			if (c1.contains(value))
				c1Value = matchValue;

			if (c2.contains(value))
				c2Value = matchValue;

			if (!(missValue == c1Value && missValue == c2Value))
				return 0;

			float a = c1Value;
			float b = c2Value;

			numerator += (a * b);
			aSquaredSum += Math.pow(a, 2);
			bSquaredSum += Math.pow(b, 2);
		}

		float denominator = (float) (Math.sqrt(aSquaredSum) * Math.sqrt(bSquaredSum));

		float similarity = numerator / denominator;

		if ((!(similarity <= 1.0f)) || (!(similarity >= -1.0f)))
			return 0;

		return similarity;
	}