具有不同数据类型的Scala数组

时间:2021-07-26 16:53:21

*as we know that scala array contains data of the same type. But when I declared array as

我们知道scala数组包含相同类型的数据。但当我声明数组为

var a = new Array[Any](3)

I am able to store different data types.

我可以存储不同的数据类型。

a(0)=5
a(1)="hello"
a(2)=1.5

how is it possible? if it is wrong then what is the option we have in scala to store different data types?*

怎么可能?如果是错误的,那么我们在scala中有什么选项来存储不同的数据类型

3 个解决方案

#1


3  

The notion of "same type" always depends on a level of generality. In Scala, the level of generality is determined by formal type.

“同一类型”的概念总是取决于一定程度的普遍性。在Scala中,通用性的级别由形式类型决定。

Are 3 and 7 "of the same type"? If we write...

3和7是同一类型的吗?如果我们写…

val a : Int = 3
val b : Int = 7

then they of of the same type Int. But, if we define bit-length restricted Int types (which we are very welcome to do in Scala), we might write

但是,如果我们定义了位长受限的Int类型(这在Scala中是非常受欢迎的),我们可以编写

val a : Int2 = 3
val b : Int3 = 7

and they no longer appear to be of the same type!

而且它们看起来不再是同一类型!

If we define an inheritance hierarchy

如果我们定义一个继承层次结构

trait Animal;
class Dog extends Animal;
class Frog extends Animal;

then do Dog and Frog have the same type? If we write

那么狗和青蛙有相同的类型吗?如果我们写

val d : Dog  = new Dog
val f : Frog = new Frog

then it looks like the answer is no. But if we write

那么看起来答案是否定的。但是如果我们写

val d : Animal = new Dog
val f : Animal = new Frog

then they look like they do have the same type. Consistent with that, if I declare an array like

然后他们看起来确实有相同的类型。与之一致的是,如果我声明一个像这样的数组

val arr : Array[Dog] = Array.ofDim[Dog](5)

then I can't put a frog in it, because a frog is not a dog. But if I declare the a similar array

那我就不能放一只青蛙进去,因为青蛙不是狗。但是如果我声明一个类似的数组

val arr : Array[Animal] = Array.ofDim[Animal](5)

Then of course both frogs and dogs can go in it, because at the level of generality of Animal, both Frogs and Dogs do have the same type.

当然,青蛙和狗都可以进去,因为在动物的一般水平上,青蛙和狗都有相同的类型。

In Scala Any is a base type from which all other types derive. So, at a very high level of generality, 5, "hello", and 1.5, all have the same type Any, just as at a high level of generality Frog and Dog have the same type Animal. So there's no problem putting 5, "hello", and 1.5 into an Array[Any].

在Scala中Any是所有其他类型派生的基类型。所以,在一个非常高的通用性水平上,5,"你好"和1。5,都有相同类型的任何,就像高水平的一般青蛙和狗有相同类型的动物一样。因此,在数组中输入5、“hello”和1.5是没有问题的。

#2


1  

Yes you are right about scala array and you are indeed storing the data of same type here. See this example:

是的,您对scala数组的理解是正确的,您确实是在这里存储相同类型的数据。看这个例子:

scala> val a = Array(5,"hello",1.5)
a: Array[Any] = Array(5, hello, 1.5)

We don't see that an array containing an integer,string and double is created. We see that an array of Any is created. During array creation, the scala compiler looked for the nearest common supertype in hierarchy to satisfy the property of Array that it can hold elements of same type only. And in this case, Any being the supertype of all the classes, satisfies the condition. And, if the compiler can't find the common supertype, Array creation will fail.

我们没有看到一个包含整数、字符串和双精度的数组被创建。我们看到创建了任意数组。在数组创建期间,scala编译器在层次结构中寻找最近的公共超类型,以满足它只能保存相同类型元素的数组属性。在这种情况下,所有类的父类都满足条件。而且,如果编译器找不到通用的超类型,那么数组创建将失败。

Note that, it's not just for Array, same goes for other collections that store same types.for eg: List

请注意,这不仅仅是针对数组,对于存储相同类型的其他集合也是如此。如:列表

scala> val list = List(5,"hello",1.5)
list: List[Any] = List(5, hello, 1.5)

what is the option we have in scala to store different data types?

scala有什么选项可以存储不同的数据类型?

As you can see that we are not able to preserve the type of elements here in both List and Array. All the elements are being stored as Any. For preserving types of elements and storing them together, scala provides us with Tuple:

如您所见,我们无法在列表和数组中保存元素的类型。所有元素都以任何形式存储。为了保存元素的类型并将它们存储在一起,scala为我们提供了Tuple:

scala> val tuple = (5,"hello",1.5)
tuple: (Int, String, Double) = (5,hello,1.5)

#3


0  

As others have answered why Array[Any] can have elements of types String, Boolean, Int etc. let me answer the below part of the question

正如其他人所回答的,为什么数组[Any]可以有类型字符串、布尔值、Int等元素

if it is wrong then what is the option we have in scala to store different data types?*

如果是错误的,那么我们在scala中有什么选项来存储不同的数据类型

The most obvious answer is the Shapeless library. Shapeless supports an advanced data-structure called HList using which you can store heterogenous types in a list without losing the type information.

最明显的答案是没有形状的库。Shapeless支持一种叫做HList的高级数据结构,使用这种结构可以在列表中存储异构类型而不会丢失类型信息。

for example see the below snippet

例如,请参见下面的代码片段

scala> import shapeless.{::, HList, HNil}
import shapeless.{$colon$colon, HList, HNil}

scala> val list = 1 :: "a" :: true :: HNil
list: shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeless.HNil]]] = 1 :: a :: true :: HNil

scala> list.head
res0: Int = 1 // notice the type of the element is Int and not Any

scala> list.tail.head
res1: String = a

scala> list.tail.tail.head
res2: Boolean = true

In the above code you have a val list of type HList with three elements of types Int, String and Boolean. And when you retrieve the elements of the HList the original type of the elements are preserved and you don't get a generic type like Any as in the case of Array. This is possible because HList stores not just data but the type information of the elements too and properly casts them on retrieval.

在上面的代码中,您有一个HList类型的val列表,其中包含三种类型:Int、String和Boolean。当你检索HList的元素时元素的原始类型会被保留,你不会像数组那样得到一个泛型类型。这是可能的,因为HList不仅存储数据,还存储元素的类型信息,并在检索时正确地对它们进行强制转换。

#1


3  

The notion of "same type" always depends on a level of generality. In Scala, the level of generality is determined by formal type.

“同一类型”的概念总是取决于一定程度的普遍性。在Scala中,通用性的级别由形式类型决定。

Are 3 and 7 "of the same type"? If we write...

3和7是同一类型的吗?如果我们写…

val a : Int = 3
val b : Int = 7

then they of of the same type Int. But, if we define bit-length restricted Int types (which we are very welcome to do in Scala), we might write

但是,如果我们定义了位长受限的Int类型(这在Scala中是非常受欢迎的),我们可以编写

val a : Int2 = 3
val b : Int3 = 7

and they no longer appear to be of the same type!

而且它们看起来不再是同一类型!

If we define an inheritance hierarchy

如果我们定义一个继承层次结构

trait Animal;
class Dog extends Animal;
class Frog extends Animal;

then do Dog and Frog have the same type? If we write

那么狗和青蛙有相同的类型吗?如果我们写

val d : Dog  = new Dog
val f : Frog = new Frog

then it looks like the answer is no. But if we write

那么看起来答案是否定的。但是如果我们写

val d : Animal = new Dog
val f : Animal = new Frog

then they look like they do have the same type. Consistent with that, if I declare an array like

然后他们看起来确实有相同的类型。与之一致的是,如果我声明一个像这样的数组

val arr : Array[Dog] = Array.ofDim[Dog](5)

then I can't put a frog in it, because a frog is not a dog. But if I declare the a similar array

那我就不能放一只青蛙进去,因为青蛙不是狗。但是如果我声明一个类似的数组

val arr : Array[Animal] = Array.ofDim[Animal](5)

Then of course both frogs and dogs can go in it, because at the level of generality of Animal, both Frogs and Dogs do have the same type.

当然,青蛙和狗都可以进去,因为在动物的一般水平上,青蛙和狗都有相同的类型。

In Scala Any is a base type from which all other types derive. So, at a very high level of generality, 5, "hello", and 1.5, all have the same type Any, just as at a high level of generality Frog and Dog have the same type Animal. So there's no problem putting 5, "hello", and 1.5 into an Array[Any].

在Scala中Any是所有其他类型派生的基类型。所以,在一个非常高的通用性水平上,5,"你好"和1。5,都有相同类型的任何,就像高水平的一般青蛙和狗有相同类型的动物一样。因此,在数组中输入5、“hello”和1.5是没有问题的。

#2


1  

Yes you are right about scala array and you are indeed storing the data of same type here. See this example:

是的,您对scala数组的理解是正确的,您确实是在这里存储相同类型的数据。看这个例子:

scala> val a = Array(5,"hello",1.5)
a: Array[Any] = Array(5, hello, 1.5)

We don't see that an array containing an integer,string and double is created. We see that an array of Any is created. During array creation, the scala compiler looked for the nearest common supertype in hierarchy to satisfy the property of Array that it can hold elements of same type only. And in this case, Any being the supertype of all the classes, satisfies the condition. And, if the compiler can't find the common supertype, Array creation will fail.

我们没有看到一个包含整数、字符串和双精度的数组被创建。我们看到创建了任意数组。在数组创建期间,scala编译器在层次结构中寻找最近的公共超类型,以满足它只能保存相同类型元素的数组属性。在这种情况下,所有类的父类都满足条件。而且,如果编译器找不到通用的超类型,那么数组创建将失败。

Note that, it's not just for Array, same goes for other collections that store same types.for eg: List

请注意,这不仅仅是针对数组,对于存储相同类型的其他集合也是如此。如:列表

scala> val list = List(5,"hello",1.5)
list: List[Any] = List(5, hello, 1.5)

what is the option we have in scala to store different data types?

scala有什么选项可以存储不同的数据类型?

As you can see that we are not able to preserve the type of elements here in both List and Array. All the elements are being stored as Any. For preserving types of elements and storing them together, scala provides us with Tuple:

如您所见,我们无法在列表和数组中保存元素的类型。所有元素都以任何形式存储。为了保存元素的类型并将它们存储在一起,scala为我们提供了Tuple:

scala> val tuple = (5,"hello",1.5)
tuple: (Int, String, Double) = (5,hello,1.5)

#3


0  

As others have answered why Array[Any] can have elements of types String, Boolean, Int etc. let me answer the below part of the question

正如其他人所回答的,为什么数组[Any]可以有类型字符串、布尔值、Int等元素

if it is wrong then what is the option we have in scala to store different data types?*

如果是错误的,那么我们在scala中有什么选项来存储不同的数据类型

The most obvious answer is the Shapeless library. Shapeless supports an advanced data-structure called HList using which you can store heterogenous types in a list without losing the type information.

最明显的答案是没有形状的库。Shapeless支持一种叫做HList的高级数据结构,使用这种结构可以在列表中存储异构类型而不会丢失类型信息。

for example see the below snippet

例如,请参见下面的代码片段

scala> import shapeless.{::, HList, HNil}
import shapeless.{$colon$colon, HList, HNil}

scala> val list = 1 :: "a" :: true :: HNil
list: shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeless.HNil]]] = 1 :: a :: true :: HNil

scala> list.head
res0: Int = 1 // notice the type of the element is Int and not Any

scala> list.tail.head
res1: String = a

scala> list.tail.tail.head
res2: Boolean = true

In the above code you have a val list of type HList with three elements of types Int, String and Boolean. And when you retrieve the elements of the HList the original type of the elements are preserved and you don't get a generic type like Any as in the case of Array. This is possible because HList stores not just data but the type information of the elements too and properly casts them on retrieval.

在上面的代码中,您有一个HList类型的val列表,其中包含三种类型:Int、String和Boolean。当你检索HList的元素时元素的原始类型会被保留,你不会像数组那样得到一个泛型类型。这是可能的,因为HList不仅存储数据,还存储元素的类型信息,并在检索时正确地对它们进行强制转换。