Странное поведение типа Array с оператором `==`

scala> List(1,2,3) == List(1,2,3)

res2: Boolean = true

scala> Map(1 -> "Olle") == Map(1 -> "Olle")

res3: Boolean = true

Но при попытке сделать то же самое с Array это не сработает. Почему?

scala> Array('a','b') == Array('a','b')

res4: Boolean = false

Я использовал 2.8.0.RC7 и 2.8.0.Beta1-prerelease.


person olle kullberg    schedule 09.07.2010    source источник
comment
Примечание. Вы можете искать все вопросы, связанные с массивами scala, с помощью [scala] [array]   -  person oluies    schedule 09.07.2010
comment
возможный дубликат Почему ` Array (0,1,2) == Array (0,1,2) `не возвращает ожидаемый результат?   -  person Suma    schedule 21.01.2015


Ответы (2)


Потому что определение «равно» для массивов состоит в том, что они относятся к одному и тому же массиву.

Это согласуется с равенством массивов Java с использованием Object.Equals, поэтому он сравнивает ссылки.

Если вы хотите проверить попарные элементы, используйте sameElements

Array('a','b').sameElements(Array('a','b'))

или deepEquals, который устарел в 2.8, поэтому вместо этого используйте:

Array('a','b').deep.equals(Array('a','b').deep)

В Nabble есть хорошее обсуждение равенство массивов.

person Stephen    schedule 09.07.2010
comment
Является ли Array единственным исключением из общего правила сравнения фактических элементов для встроенных коллекций? Во всех других коллекциях я пробовал сравнивать элементы. - person olle kullberg; 09.07.2010
comment
@olle - насколько мне известно, это единственная коллекция, которая демонстрирует такое поведение. Даже ArrayList сравнивает элементы. Что я не могу понять, так это то, как это должно быть изучено из документации :) - person Stephen; 09.07.2010
comment
также см. stackoverflow.com/questions/2481149/ - person oluies; 09.07.2010
comment
@olle: массив java является объектом (java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html, особенно раздел 10.8) WrappedArray обертывает массив java в класс. Array - массив java. Причина, по которой он не может переопределить Object.equals (и предоставить специализированное равенство), заключается в том, что он не подклассифицирует массив java. Если бы он обернул массив или разделил его на подклассы, он бы вел себя так, как вы ожидали. Должен сказать, мой ответ полностью точен, за исключением того, что я не вдавался в подробности о почему он не может переопределить поведение. - person Stephen; 10.07.2010
comment
@olle: Кстати, ваше объяснение фактически неверно, когда вы говорите правильное объяснение ... Если вы не принимаете его, хорошо, но -1 добавляет оскорбление к травме! :) - person Stephen; 10.07.2010
comment
Мое плохое, вы правы! Я читал в Beyond Java (Б. Тейт), что массив Java не является объектом, но, как вы сказали, это неверно. - person olle kullberg; 12.07.2010
comment
@olle: Спасибо, что прояснили это. И я буду держаться подальше от этой книги :) - person Stephen; 12.07.2010

Основная причина заключается в том, что Scala использует ту же реализацию массива, что и Java, и это единственная коллекция, которая не поддерживает == в качестве оператора равенства.

Также важно отметить, что выбранный ответ предлагает одинаковое sameElements и deep сравнение, хотя на самом деле его предпочтительно использовать:

Array('a','b').deep.equals(Array('a','b').deep)

Или, потому что теперь мы можем снова использовать ==:

Array('a','b').deep == Array('a','b').deep

Вместо:

Array('a','b').sameElements(Array('a','b'))

Поскольку sameElements не предназначен для вложенного массива, он не рекурсивен. И deep сравнение будет.

person Johnny    schedule 12.04.2018
comment
Любопытно, что начиная с Scala 2.13.0 .deep больше не является членом Array. - person jwvh; 01.07.2020