user1111284
user1111284

Reputation: 906

Deep compare arrays in tuples in Scala

I'm trying to compare tuples containing arrays in Scala as part of some tests and running into a problem where it seems to compare the array objects rather than the contents.

Comparing arrays themselves works fine; this passes:

assertResult(Array[Byte](0.toByte, 2.toByte))(Array[Byte](0.toByte, 2.toByte))

However, when I put the array into a tuple, paired with a long, I get an exception

This is the test code:

assertResult((12345678L, Array[Byte](0.toByte, 2.toByte)))((12345678L, Array[Byte](0.toByte, 2.toByte)))

and the exception I get is:

org.scalatest.exceptions.TestFailedException: Expected (12345678,[B@2473d930), but got (12345678,[B@35047d03)

From the way it prints out the memory location of the arrays, it makes me think it's comparing the object references rather than deep comparing each object in the array.

Is this expected in Scala, or am I doing something wrong here? Thanks for reading.

Upvotes: 1

Views: 1291

Answers (2)

user2864740
user2864740

Reputation: 61885

That is correct, per Java's array equality (or lack of) behavior.

As seen in the message ([B@2473d930) the Scala Array type is a fancy skin for a Java-array; but it can't change how a Java array instance actually works.

The most straight forward solution is probably to use a collection type that properly implements == (aka Object.equals).

Tuple1(Array(1)) == Tuple1(Array(1))  // false
Tuple1(List(1)) == Tuple1(List(1))    // true

(See m-z's answer for why the non-nested case works.)

Upvotes: 2

Michael Zajac
Michael Zajac

Reputation: 55569

It will work if you call deep on the Arrays:

assertResult((12345678L, Array[Byte](0.toByte, 2.toByte).deep))((12345678L, Array[Byte](0.toByte, 2.toByte).deep))

This actually just converts the Array to an IndexedSeq so it can do the equals comparison (instead of the default reference comparison on Array). It seems as though assertResult does this for you if the top level comparison is an Array, but not if the Array is nested within another object. This is why the first example works, but the second does not.

Given that, it's probably very inconvenient to have to do this, and you might consider using a different collection type other than Array.

Upvotes: 6

Related Questions