Как назначить порядок для TreeSet в Scala, не повторяясь

У меня есть этот сегмент кода Scala, который определяет порядок и применяет его к TreeSet. Эта часть компилируется нормально.

val acctOrdering = new Ordering[Account] {
  def compare(acc1: Account, acc2: Account) {

    // code to compare based on various criteria

  }
}

private var accountSet = new TreeSet[Account]()(acctOrdering)

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

val firstAccount = accountSet.min

Ошибка "could not find implicit value for parameter cmp: Ordering[Account]"

Однако, если я снова укажу объект заказа при запросе минимума, он скомпилируется:

val firstAccount = accountSet.min(acctOrdering)

Я думал, что он будет автоматически использовать порядок, который я задал во время построения, и постепенно сортировать по мере добавления в набор, поэтому мне не нужно было бы снова указывать порядок при вызове min.

Что я делаю не так? Нужно ли где-то явно определять неявную функцию?


person Gigatron    schedule 27.03.2011    source источник


Ответы (1)


Происходит то, что вы предполагаете, что min зависит от порядка набора, но это не так. В частности, min и max являются универсальными методами, доступными практически для любой коллекции, и они принимают неявный параметр Ordering.

Однако, если вы попробуете firstKey и lastKey, которые являются специфическими для SortedSet методами, они будут работать без необходимости передавать какие-либо неявные значения.

Изменить

Один из вопросов, который вы могли задать, заключается в том, как убедиться, что ваш тип Account может быть упорядочен любым методом, ожидающим Ordering. Вы можете сделать это, поместив неявное определение внутри объекта-компаньона Account, например:

object Account {
  implicit val ord = new Ordering[Account] {
    def compare(ac1: Account, acc2: Account): Int = {
      // code to compare based on various criteria
    }
  }
}

Как только вы это сделаете, вам не нужно будет явно передавать порядок.

person Daniel C. Sobral    schedule 27.03.2011
comment
Спасибо. Изменение min на firstKey приводит к компиляции. Есть две версии min, одна без параметра и другая с имплицитным. Просто для моего понимания, как будет использоваться метод def min : A? - person Gigatron; 28.03.2011
comment
Хорошо, теперь я думаю, что понял... похоже, что min без параметров никогда не используется в TreeSet, потому что вызов его без параметра всегда будет возвращаться к версии min, которая ожидает неявный параметр. - person Gigatron; 28.03.2011
comment
@Gigatron Есть только одно определение min. Другое определение, которое вы видите в ScalaDoc, помечено как вариант использования. Это означает, что это не настоящая подпись, а фальшивая подпись, которая представляет то, что происходит большую часть времени. В этом случае вызов min без каких-либо параметров будет работать в большинстве случаев. - person Daniel C. Sobral; 28.03.2011
comment
@Gigatron Однако теперь я вижу, что мог бы быть более полезным в своем ответе, поэтому см. Редактирование для получения дополнительной информации. - person Daniel C. Sobral; 28.03.2011
comment
Спасибо за разъяснение, особенно по поводу варианта использования. В этой ситуации конкретный порядок предназначен для очень конкретной цели, которая бесполезна для остальной части приложения, поэтому я не буду размещать порядок в самой учетной записи. - person Gigatron; 28.03.2011
comment
какой тип возврата для сравнения ()? В Java compareTo возвращает логическое значение. - person Adrian; 06.06.2013
comment
@Adrian То же, что и в Java: Int, а не Boolean, как вы утверждали. Обратите внимание, что Ordering эквивалентен Comparator в Java, а не Comparable, а метод compare в Comparable также возвращает Int. И JavaDoc, и ScalaDoc документируют точное значение возвращаемого Int. - person Daniel C. Sobral; 07.06.2013
comment
@DanielC.Sobral, ты прав! Это инт.. Должно быть, я очень устал. Мое замешательство было в том, что я не видел тип возвращаемого значения в методе сравнения; Я предположил, что это Юнит... что не имело смысла. - person Adrian; 07.06.2013
comment
@Adrian Что ж, оставлять тип возвращаемого значения в общедоступном методе - плохой тон, поэтому я исправил это сейчас. - person Daniel C. Sobral; 07.06.2013