加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

泛型 – 通用数据结构的默认值

发布时间:2020-12-16 08:48:51 所属栏目:安全 来源:网络整理
导读:我想写一个SparseVector [T]类,其中T可以是double,int或boolean. 该类不会被数组支持(因为我想要一个稀疏数据结构)但我已经看到,当我构建一个AnyVal类型的空数组时,元素被初始化为默认值.例如: scala new Array[Int](10) res0: Array[Int] = Array(0,0) sca
我想写一个SparseVector [T]类,其中T可以是double,int或boolean.

该类不会被数组支持(因为我想要一个稀疏数据结构)但我已经看到,当我构建一个AnyVal类型的空数组时,元素被初始化为默认值.例如:

scala> new Array[Int](10)
 res0: Array[Int] = Array(0,0)

 scala> new Array[Boolean](10)
 res1: Array[Boolean] = Array(false,false,false)

 scala> new Array[Double](10) 
 res2: Array[Double] = Array(0.0,0.0,0.0)

如何在班级中包含此默认值?我想要的行为是:

val v = new SparseVector[Double](100)
println( v(12) ) // should print '0.0'
val w = new SparseVector[Boolean](100)
println( v(85) ) // should print 'false'

谢谢

解决方法

您可以利用Scala已经为您提供获取类型默认值的方法这一事实.当你写var x:Int = _时,这会将x初始化为0.类似于所有AnyVal类型.所有AnyRef类型都初始化为null.

记住这一点,您可以重写稀疏的矢量类,如下所示:

class SparseVector[T](val size: Int) {
  import scala.collection.mutable.Map

  private var default: T = _
  private[this] val storage = Map[Int,T]() 

  def apply(key: Int) = 
    if(key < size)
      storage.getOrElse(key,default)
    else 
      throw new IllegalArgumentException("Index "  + key + " out of bounds")

  def update(key: Int,value: T) { storage(key) = value }
}

现在代码如下所示按预期工作:

scala> val b = new SparseVector[Boolean](10)
b: SparseVector[Boolean] = SparseVector@cfd22a

scala> b(1)
res20: Boolean = false

scala> b(1) = true

scala> b(1)
res22: Boolean = true

scala> val i = new SparseVector[Int](10)
i: SparseVector[Int] = SparseVector@1813c12

scala> i(1)
res23: Int = 0

scala> i(1) = 10

scala> i(1)
res25: Int = 10

scala> i(10)
java.lang.IllegalArgumentException: Index 10 out of bounds

我可能会对这个课程做一些改进:

>使用`toString`方法以合理的方式打印集合
>提供一个伴随对象,如果需要,可以更改向量的默认值(请参阅下面的代码).

object SparseVector {
  def apply[T](size: Int) = new SparseVector[T](size)
  def apply[T](size: Int,default: T) = {
    val result = new SparseVector[T](size)
    result.default = default

    result
  }
}

现在这个工作:

scala> val b = SparseVector[Boolean](10,true)
b: SparseVector[Boolean] = SparseVector@126f29f

scala> b(4)
res28: Boolean = true

scala> val i = SparseVector[Int](10,42)
i: SparseVector[Int] = SparseVector@b9979b

scala> i(3)
res30: Int = 42

编辑:我编写的代码适用于Scala 2.7.6.final. Mitch Blevins指出,当使用Scala 2.8r.19890运行时,代码会将null作为AnyVal类型的默认值.正如评论中所解释的那样,这不应该是可能的,因为Null不是AnyVal的子类型.如果使用2.8,一般的想法应该是相似的,因为var b:Boolean = _仍然应该给你布尔类型的默认值.使用集合存储稀疏向量可能会有所不同,但正如我在评论中所说,我不熟悉2.8集合的重新设计.

EDIT2:…无法实现null行为,但遗憾的是它.做一些more research into the problem似乎由于类型擦除,字段默认值始终初始化为null.之后……奇怪随之而来.有关讨论,请参阅Mitch’s post,以及一些重现问题的熊骨代码.

为了使代码正常工作,我尝试过但失败了:

> null.asInstanceOf [T] – 不,Java没有具体化的泛型.这仍然是空的
> @specialised – nope,似乎即使编译器为基元生成专门的代码,你仍然会得到null行为
>将结果转换为AnyVal,该值不应为null.不.仍然无效.

从概念上讲,我的解决方案应该有效.但它不是由于我在Scala Trac中有reported的非常奇怪的行为.

有关可为空的AnyVals的详细讨论,另请参阅this blog post.

– Flaviu Cipcigan

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读