Являются ли голова и хвост набора гарантией взаимоисключающим?

Документация говорит, что Set.head возвращает "первый" элемент, а .tail возвращает "все, кроме первого". * Поскольку a Set doesn На самом деле у него есть "первый" элемент, документация предупреждает, что без упорядоченного типа вы можете получить другой результат на разных прогонах. Но гарантированы ли вы, что хвост не будет включать голову?

Причина, по которой я спрашиваю, - мне интересно, нормально ли это записать Set следующим образом:

def recurse(itemsToExamine: Set[Item], acc: Result): Result =
  if (itemsToExamine.isEmpty) acc
  else {
    val item = itemsToExamine.head
    recurse(
      item.spawnMoreItems ++ itemsToExamine.tail,
      acc.updatedFor(item))
  }

Если это законно, это, безусловно, будет лучше, чем преобразование с Set в Seq и обратно, чтобы разделить голову и хвост на каждой рекурсии.


* Фактически, он говорит "выбирает первый элемент" и "выбирает все, кроме первого элемента". Я предполагаю, что "выбор" - это просто плохой выбор слова. Если есть причина говорить "выбирает", а не "возвращает", пожалуйста, дайте мне знать.

Ответ 1

Я не уверен на 100%, потому что я не слишком много смотрел на реализацию, но для любого HashSet существует неявное упорядочение на основе hashCode (типа Int) значения, которые уже находятся в Set.

Это означает, что для любого экземпляра Set вызовы head и tail будут относиться к этому упорядочению, поэтому он не будет тем же самым элементом. Более того, последовательная итерация через элементы данного экземпляра Set должна приводить элементы в том же порядке, потому что Set является неизменным.

Вывод заключается в том, что, пока порядок неизвестен, для любого экземпляра есть один, который может измениться, как только вы добавите (изменчиво или неизменно) новый элемент в Set.

Ответ 2

Опора на head и tail на Set (без упорядочивания) в лучшем случае является рискованной.

В вашем случае просто выберите Iterator из своего Set сначала с помощью theSet.toIterator, а затем перезапустите итератор. Итератор гарантирует, что первый элемент будет отличаться от остальных, конечно.

Ответ 3

Вы можете сделать это:

val set = Set(1, 2, 3)
val head = set.head
val tail = set - head

Это гарантирует, что они будут взаимоисключающими.