Мне нужно обработать большое количество записей (несколько миллионов), представляющих людей. Я хотел бы создать раздел по году рождения, а затем обрабатывать каждую группу отдельно. Я пытаюсь создать функциональное решение (без/минимальные изменяемые данные), чтобы оно было потокобезопасным и могло быть распараллелено.
В качестве первой попытки я создал хвостовую рекурсивную функцию, которая создает Map[Int, IndexedSeq]
, сопоставляющую каждый год рождения с последовательностью записей о людях. Мне нужна проиндексированная последовательность, потому что я буду выполнять произвольный доступ к людям в каждой группе. Вот мой код:
@tailrec
def loop(people: Seq[Person],
map: Map[Int, IndexedSeq[Person]] = Map()): Map[Int, IndexedSeq[Person]] = {
if (people.isEmpty) map
else {
val person = people.head
val yearOfBirth = person.yearOfBirth
val seq = map.getOrElse(yearOfBirth, IndexedSeq())
loop(people.tail, map + (yearOfBirth -> (seq :+ person)))
}
}
Это работает, но не очень эффективно. Я могу добиться большего успеха, разрешив небольшое количество очень локализованной изменчивости. Если все изменяемые переменные находятся в стеке, код по-прежнему будет потокобезопасным, пока вывод Map
неизменен.
Я хотел бы реализовать это путем внутреннего создания изменяемого Map[Int, List[Person]]
, а затем эффективно преобразовать его в неизменяемый Map[Int, IndexedSeq[Person]]
в качестве возвращаемого значения.
Как преобразовать изменяемые Map
из List
элементов в неизменяемые Map[Int, IndexedSeq[Person]]
наиболее эффективным способом? Обратите внимание, что для людей в каждой группе года рождения нет определенного порядка.