How to get a correct array hashcode in scala? - arrays

What is the suitable way to compute hashCode of an Array that depends on its content?
Array.hashCode is for the array instance:
val h = a.hashCode
println(h == Array(1,2).hashCode) // false
a(0) = 42
println(h == a.hashCode) // true
Note: It'd be better to avoid copying the whole array, to a List for example, prior to computing the hashCode
Why I ask: I use an Array in a class (as a private field) because lookup time is critical, and its content is relevant to compute the hashCode of the class

from https://issues.scala-lang.org/browse/SI-1607, it says that the hashCode of Array is the hashCode from java, as scala Array are java Array. And scala could not changed it.
But it also says that scala has a suitable hashCode method in WrappedArray.
Thus:
val a = Array(1,2)
val h = a.toSeq.hashCode // wrapped it in a WrappedArray - no copy
println(h == Array(1,2).toSeq.hashCode) // true
a(0) = 42
println(h == a.toSeq.hashCode) // false

You can also use java.util.Arrays.hashCode(a), it's likely to be faster than a.toSeq.hashCode (since WrappedArray seems to inherit a non-array-specific implementation).

You can use the MurmurHash3 algorithm directly.
import scala.util.hashing.MurmurHash3
MurmurHash3.orderedHash(Array(1,2)))

Related

Range of an Array or List in Kotlin when it does not have to accommodate the empty case

I'm looking to calculate the range of a list or array and was frustrated by not being able to simply take the difference of the max() and min() functions due to null safety feature of Kotlin.
I came up with this solution which is forcing me to deal with the case of an ifEmpty() even if I know that is not possible in with this immutable array. I wonder if there is something simpler without the extra characters.
val array=arrayOf(1,2,3,4,5)
// doesn't compile... val range = array.max()-array.min()
val range = (array.max() ?: 0) - (array.min() ?: 0)
This isn't much different, but since you know that it isn't empty, you can use !! (the Hold My Beer operator), to tell Kotlin to ignore the nullability of the types.
val range = if(array.isEmpty()) 0 else array.max()!! - array.min()!!
It might also be handy to define an extension if you anticipate doing this a lot:
fun Array<Int>.range(): Int =
if(isEmpty()) 0 else max()!! - min()!!
// Usage
val range = array.range()

Difference between List and Array types in Kotlin

What is the difference between List and Array types?
It seems can make same operations with them (loops, filter expression, etc..), is there any difference in behavior or usage?
val names1 = listOf("Joe","Ben","Thomas")
val names2 = arrayOf("Joe","Ben","Thomas")
for (name in names1)
println(name)
for (name in names2)
println(name)
Arrays and lists (represented by List<T> and its subtype MutableList<T>) have many differences, here are the most significant ones:
Array<T> is a class with known implementation: it's a sequential fixed-size memory region storing the items (and on JVM it is represented by Java array).
List<T> and MutableList<T> are interfaces which have different implementations: ArrayList<T>, LinkedList<T> etc. Memory representation and operations logic of lists are defined in concrete implementation, e.g. indexing in a LinkedList<T> goes through the links and takes O(n) time whereas ArrayList<T> stores its items in a dynamically allocated array.
val list1: List<Int> = LinkedList<Int>()
val list2: List<Int> = ArrayList<Int>()
Array<T> is mutable (it can be changed through any reference to it), but List<T> doesn't have modifying methods (it is either read-only view of MutableList<T> or an immutable list implementation).
val a = arrayOf(1, 2, 3)
a[0] = a[1] // OK
val l = listOf(1, 2, 3)
l[0] = l[1] // doesn't compile
val m = mutableListOf(1, 2, 3)
m[0] = m[1] // OK
Arrays have fixed size and cannot expand or shrink retaining identity (you need to copy an array to resize it). As to the lists, MutableList<T> has add and remove functions, so that it can increase and reduce its size.
val a = arrayOf(1, 2, 3)
println(a.size) // will always be 3 for this array
val l = mutableListOf(1, 2, 3)
l.add(4)
println(l.size) // 4
Array<T> is invariant on T (Array<Int> is not Array<Number>), the same for MutableList<T>, but List<T> is covariant (List<Int> is List<Number>).
val a: Array<Number> = Array<Int>(0) { 0 } // won't compile
val l: List<Number> = listOf(1, 2, 3) // OK
Arrays are optimized for primitives: there are separate IntArray, DoubleArray, CharArray etc. which are mapped to Java primitive arrays (int[], double[], char[]), not boxed ones (Array<Int> is mapped to Java's Integer[]). Lists in general do not have implementations optimized for primitives, though some libraries (outside JDK) provide primitive-optimized lists.
List<T> and MutableList<T> are mapped types and have special behaviour in Java interoperability (Java's List<T> is seen from Kotlin as either List<T> or MutableList<T>). Arrays are also mapped, but they have other rules of Java interoperability.
Certain array types are used in annotations (primitive arrays, Array<String>, and arrays with enum class entries), and there's a special array literal syntax for annotations. Lists and other collections cannot be used in annotations.
As to the usage, good practice is to prefer using lists over arrays everywhere except for performance critical parts of your code, the reasoning is the same to that for Java.
The major difference from usage side is that Arrays have a fixed size while (Mutable)List can adjust their size dynamically. Moreover Array is mutable whereas List is not.
Furthermore kotlin.collections.List is an interface implemented among others by java.util.ArrayList. It's also extended by kotlin.collections.MutableList to be used when a collection that allows for item modification is needed.
On the jvm level, Array is represented by arrays. List on the other hand is represented by java.util.List since there are no immutable collections equivalents available in Java.
In additional to the above, identity comparison is also different:
val l1 = listOf("a")
val l2 = listOf("a")
var x = (l1 == l2) // => true
val a1 = arrayOf("a")
val a2 = arrayOf("a")
var y = (a1 == a2) // => false

What is the difference between ArrayBuffer and Array

I'm new to scala/java and I have troubles getting the difference between those two.
By reading the scala doc I understood that ArrayBuffer are made to be interactive (append, insert, prepend, etc).
1) What are the fundamental implementation differences?
2) Is there performance variation between those two?
Both Array and ArrayBuffer are mutable, which means that you can modify elements at particular indexes: a(i) = e
ArrayBuffer is resizable, Array isn't. If you append an element to an ArrayBuffer, it gets larger. If you try to append an element to an Array, you get a new array. Therefore to use Arrays efficiently, you must know its size beforehand.
Arrays are implemented on JVM level and are the only non-erased generic type. This means that they are the most efficient way to store sequences of objects – no extra memory overhead, and some operations are implemented as single JVM opcodes.
ArrayBuffer is implemented by having an Array internally, and allocating a new one if needed. Appending is usually fast, unless it hits a limit and resizes the array – but it does it in such a way, that the overall effect is negligible, so don't worry. Prepending is implemented as moving all elements to the right and setting the new one as the 0th element and it's therefore slow. Appending n elements in a loop is efficient (O(n)), prepending them is not (O(n²)).
Arrays are specialized for built-in value types (except Unit), so Array[Int] is going to be much more optimal than ArrayBuffer[Int] – the values won't have to be boxed, therefore using less memory and less indirection. Note that the specialization, as always, works only if the type is monomorphic – Array[T] will be always boxed.
The one other difference is, Array's element created as on when its declared but Array Buffer's elements not created unless you assign values for the first time.
For example. You can write Array1(0)="Stackoverflow" but not ArrayBuffer1(0)="Stackoverflow" for the first time value assignments.
(Array1 = Array variable & ArrayBuffer1 = ArrayBuffer variable)
Because as we know, Array buffers are re-sizable, so elements created when you insert values at the first time and then you can modify/reassign them at the particular element.
Array:
Declaring and assigning values to Int Array.
val favNums= new Array[Int](20)
for(i<-0 to 19){
favNums(i)=i*2
}
favNums.foreach(println)
ArrayBuffer:
Declaring and assigning values to Int ArrayBuffer.
val favNumsArrayBuffer= new ArrayBuffer[Int]
for(j<-0 to 19){
favNumsArrayBuffer.insert(j, (j*2))
//favNumsArrayBuffer++=Array(j*3)
}
favNumsArrayBuffer.foreach(println)
If you include favNumsArrayBuffer(j)=j*2 at the first line in the for loop, It doesn't work. But it works fine if you declare it in 2nd or 3rd line of the loop. Because values assigned already at the first line now you can modify by element index.
This simple one-hour video tutorial explains a lot.
https://youtu.be/DzFt0YkZo8M?t=2005
Use an Array if the length of Array is fixed, and an ArrayBuffer if the length can vary.
Another difference is in term of reference and value equality
Array(1,2) == Array(1,2) // res0: Boolean = false
ArrayBuffer(1, 2) == ArrayBuffer(1,2) // res1: Boolean = true
The reason for the difference is == routes to .equals where Array.equals is implemented using Java's == which compares references
public boolean equals(Object obj) {
return (this == obj);
}
whilst ArrayBuffer.equals compares elements contained by ArrayBuffer using sameElements method
override def equals(o: scala.Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (
o match {
case it: Seq[A] => (it eq this) || (it canEqual this) && sameElements(it)
case _ => false
}
)
Similarly, contains behaves differently
Array(Array(1,2)).contains(Array(1,2)) // res0: Boolean = false
ArrayBuffer(ArrayBuffer(1,2)).contains(ArrayBuffer(1,2)) // res1: Boolean = true

Concise notation for last element of an array

Is there a concise notation to access last element of an array, similar to std::vector::back() in C++? Do I have to write:
veryLongArrayName.[veryLongArrayName.Length-1]
each time?
Expanding from comment
The built-in option is Seq.last veryLongArrayName, but note that this is O(N) rather than O(1), so for all but the smallest arrays probably too inefficient for practical use.
That said, there's no harm in abstracting this functionality yourself:
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
module Array =
let inline last (arr:_[]) = arr.[arr.Length - 1]
Now you can do Array.last veryLongArrayName with no overhead whatsoever, while keeping the code very idiomatic and readable.
I can not find it in the official documents, but F# 4 seems to have Array.last implemented out of the box:
/// Returns the last element of the array.
/// array: The input array.
val inline last : array:'T [] -> 'T
Link to implementation at github.
As an alternative to writing a function for _[], you can also write an extension property for IList<'T>:
open System.Collections.Generic
[<AutoOpen>]
module IListExtensions =
type IList<'T> with
member self.Last = self.[self.Count - 1]
let lastValue = [|1; 5; 13|].Last // 13

Is it sensible to use AS3 Vectors for class instances?

Here is a simple code :
var a:Array = new Array( ins0, ins1, ins2, ins3,...., ins10000) ;
findIns( ins1500) ;
function findIns( ins:SomeInstance ) {
for ( var i = 0 ; i< a.length ; i++) {
if ( a[i] == ins ) {
trace ( "FOUND IT");
break;
}
}
}
In the above code there is NO "int" or "string". They are instances of some complex class. So is it sensible to use Vectors in place of arrays in this case.
In my opinion it should be sensible, because instances are "numerical-memory-locations" afterall ?
If the content of the array are all instances of the same class, then yes Vector will definitely performs better than Array.
See the documentation for more information:
Performance: array element access and iteration are much faster when using a Vector instance than they are when using an Array.
Type safety: in strict mode the compiler can identify data type errors. Examples of data type errors include assigning a value of the incorrect data type to a Vector or expecting the wrong data type when reading a value from a Vector. Note, however, that when using the push() method or unshift() method to add values to a Vector, the arguments' data types are not checked at compile time. Instead, they are checked at run time.
Reliability: runtime range checking (or fixed-length checking) increases reliability significantly over Arrays.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Vector.html
Yes, you are right. What gets stored inside the vector is a reference to your object, not your object itself. You can check that doing the following:
var ref:yourType = a[0];
a[0] = someOtherObjectInstance;
trace(ref.toString());
You will find that ref still points to your original object.

Resources