То, что вы хотите сделать, намного сложнее, чем простая группировка по ключу.Одно из возможных решений - начать с уже посчитанных слов в countData
и выполнить декартово произведение с самим собой, используя cartesian()
.Результатом будет СДР с такими элементами, как
((to,1),(tom,1))
. Для каждой такой пары вы проверяете, соответствует ли второй ключ частичному первому (или наоборот), и выводите ключ из первой пары и значение изсекунда.Поскольку декартово произведение симметрично, обработка всех пар не является строго необходимой, только пары, в которых первый ключ лексикографически меньше или равен второму:
((to,1),(tom,1)) -> (to,1) since to <= tom and to partially matches tom
((tom,1),(to,1)) -> (to,0) since tom > to
((to,1),(to,1)) -> (to,1) since to <= to and to (partially) matches to
После этого сопоставления вам нужно только выполнитьуменьшение суммы с помощью reduceByKey
, и результат будет именно тем, что вы ищете.
Java не является моим языком выбора, поэтому я не могу дать вам рабочий код, но он должен выглядеть примерно так:
JavaPairRDD partialMatchData = countData
.cartesian(countData)
.mapToPair(t -> new Tuple2(t._1._1, partialMatch(t._1._1, t._2._1, t._2._2)))
.reduceByKey((x, y) -> (int)x + (int)y);
Прототип partialMatch
равен (String key1, String key2, int count2)
и возвращает count2
, если key1 <= key2
иначе 0
.