Я не могу объяснить это поведение наборов Scala.Scala mutable set: странное поведение
Начнем с нескольких определений.
import scala.collection.mutable.Set
case class Item(name: String, content: Set[Int])
val items: Set[Item] = Set.empty
Я добавлю товар в свой комплект.
items += Item("name", Set(1, 2, 3))
Я освобожу свой внутренний комплект.
items.filter(_.name == "name") foreach (_.content -= 1)
items
// res7: scala.collection.mutable.Set[Item] = Set(Item(name,Set(2, 3)))
Пока все хорошо.
items.filter(_.name == "name") foreach (_.content -= 2)
items.filter(_.name == "name") foreach (_.content -= 3)
items
// res12: scala.collection.mutable.Set[Item] = Set(Item(name,Set()))
Отлично! Теперь, что я ДЕЙСТВИТЕЛЬНО хочу сделать, это удалить записи с пустым внутренним набором.
items.retain(_.content.nonEmpty)
items
// res12: scala.collection.mutable.Set[Item] = Set(Item(name,Set()))
Не работает. Возможно, я сделал противоположный тест.
items.retain(_.content.isEmpty)
items
// res14: scala.collection.mutable.Set[Item] = Set(Item(name,Set()))
Не работает. Возможно, фильтр не работает.
items.filter(_.content.nonEmpty)
// res15: scala.collection.mutable.Set[Item] = Set()
Фильтр отлично работает. Может быть, я не могу его изменить, потому что это вал.
items += Item("name", Set.empty)
items
// res17: scala.collection.mutable.Set[Item] = Set(Item(name,Set()), Item(name,Set()))
Я МОГУ его изменить. И добавить ... больше того же? Возможно, они все разные.
items += Item("name", Set.empty)
items
// res19: scala.collection.mutable.Set[Item] = Set(Item(name,Set()), Item(name,Set()))
Они не все разные. Так можно ли удалить любой из них?
items -= Item("name", Set.empty)
items
// res21: scala.collection.mutable.Set[Item] = Set(Item(name,Set()))
Я могу удалить ОДИН. Могу ли я удалить другой, тот, который я пытался удалить с самого начала?
items -= Item("name", Set.empty)
items
// res23: scala.collection.mutable.Set[Item] = Set(Item(name,Set()))
Nope. Что происходит? Я очень смущен.
РЕДАКТИРОВАТЬ, РЕШЕНИЕ:
Используя этот пост StackOverflow, Scala: Ignore case class field for equals/hascode?, я решил это путем изменения способа я объявить класс случай:
case class Item(name: String)(val content: Set[Int])
Таким образом, внутренний набор игнорируется для хэш-код и равноценен, но все же доступен как поле.
Никогда не импортируйте 'mutable.Set' только когда-либо импортирует 'mutable', а затем использует' mutable.Set' в области. Это лучшая практика, потому что mutable следует избегать, как чуму, и сделать ее действительно явной для любого читателя, что вы используете изменяемые типы. – samthebest
Я пытался избежать изменчивости, но в какой-то момент это стало необходимым. Другое решение состоит в том, чтобы сделать поле содержимого «var», и это кажется намного хуже. Кроме того, значение всегда изменяется или запрашивается при получении сообщения в конкретном объекте «объект», поэтому, по крайней мере, нет реальной проблемы параллелизма. – eje211
Да, конечно, иногда это хорошо, особенно для оптимизации на низком уровне или для избежания использования рекурсии. Дело в том, что вы должны просто сделать это очень явным, используя 'mutable.Set', abd также и не должен загрязнять пространство имен, поскольку по умолчанию это' immutable.Set' – samthebest