Я борюсь с отсутствием Java в Iterator.remove()
в Scala. В частности, я хочу за один проход по большой изменяемой карте удалить элементы, которые удовлетворяют предикату, и собрать их в другую изменяемую карту.
Вот что я пытаюсь сделать:
def main(args: Array[String]) {
val map = new TrieMap[String, Integer]();
map += "one" -> 1
map += "two" -> 2
// Remove all elems whose value is > 1 and put them in val removed.
val removed = removeIf(map, _._2 > 1)
}
def removeIf(
map: mutable.Map[String, Integer],
p: ((String, Integer)) => Boolean): mutable.Map[String, Integer] = {
val result = mutable.Map[String, Integer]()
val iter = map.iterator
while (iter.hasNext) {
val elem = iter.next()
if ( p(elem) ) {
iter.remove() // Error
result += elem
}
}
result
}
По какой-то веской причине Scala Iterator
, даже в изменчивой коллекции, не реализует remove()
.
Редактировать
Ниже представлены два решения:
Не беспокойтесь о стоимости второго прохода и используйте filter (), а затем --=
, чтобы удалить отфильтрованные записи:
val результат = map.filter (p)
карта - = result.keys
Используйте раздел и переназначьте новую карту старой переменной:
(результат, newMap) = map.partition ({case (k, v) => ...})
Я провел несколько тестов. Как и ожидалось, первое решение на самом деле быстрее, в случаях, когда количество удаленных записей меньше по сравнению с размером исходной карты. Точка перегиба, где два решения работают примерно в одно и то же время, - это когда предикат разделяет исходную карту примерно пополам. Второе решение, кажется, не зависит от этого, но, очевидно, первое. Оба O (n), так что, возможно, я здесь слишком разборчив. Я хотел бы разделить галочку между двумя ответами. Спасибо и Дону Брэнсону, и мошеннику.