这是一个非常具体的要求,因此在深入研究代码之前,请允许我提出一个假设的案例。
假设您的表中有很多行是相同的-为了将一行与另一行区分开,我们希望可能添加一个随机数列,该列可以帮助防止数据倾斜。例如:
--------------------------
| MyClass1 |
--------------------------
| value1 | value2 | skew |
--------------------------
| 4 | 6 | 4962 |
--------------------------
| 4 | 6 | 6510 |
--------------------------
| 500 | 700 | 0 |
--------------------------
| 500 | 700 | 0 |
--------------------------
在这种情况下,偏斜有助于防止将数据聚集到一个位置。
一个人可以做以下事情:
case class MyClass1(value1: Int, value2: Int, skew: Int)
和偏斜的实例化将留给调用者,即:
MyClass1(value1 = 4, value2 = 6, skew = ComplexFunc(value1, value2))
但是,假设我有很多需要该偏斜值的类。在这种情况下,为每个实现都容易出错,而且还要求调用者知道偏斜值。因此,我想像这样隐藏偏斜值及其实现:
case class SkewClass(skew: Int)
object SkewClass {
def apply(skewCondition: Boolean) : SkewClass = {
if (skewCondition) SkewClass(RandomInt()) else SkewClass(0)
}
}
case class MyClass1 extends SkewClass(
val value1 : Int = 0
val value2 : Int = 0
val skew : Int = this.apply(value1 != 500 && value2 != 700)
}
简而言之,我希望能够创建MyClass1实例,并在其末尾添加一个可能为随机的整数,称为“偏斜”。即:
scala> val x = MyClass1(value1 = 500, value2 = 700)
x: MyClass1 = MyClass1(500, 700, 0)
scala> val y = MyClass1(value1 = 52, value2 = 63)
y: MyClass1 = MyClass1(52, 63, 5347)
scala>
很显然,上面的代码无法编译(我对scala还是很陌生),但是有没有办法修改此代码以允许使用此随机整数?
答案 0 :(得分:1)
在这种情况下,您希望所有结构共享属性Skew
,但不必共享任何其他详细信息。最好的解决方案是在此处使用特征。
trait Skew {
def skewCondition: Boolean
lazy val skew: Int = if (skewCondition) RandomInt() else 0
}
case class AlwaysSkew(v1: Int, v2: Int) extends Skew {
override val skewCondition: Boolean = true
}
case class ConditionalSkew(v1: Int, v2: Int) extends Skew {
override val skewCondition: Boolean = (v1 != 500) && (v2 != 700)
}
val x = ConditionalSkew(500, 700)
val y = ConditionalSkew(1234,5678)
x.skew //0
y.skew //A random Int
答案 1 :(得分:1)
您不能使用从其他字段初始化的字段来创建 <StackPanel>
<TextBlock
Background="Lavender"
FontSize="32"
Text="1+2=3"
Language="ar-EA"
FlowDirection="RightToLeft"/>
</StackPanel>
,但是可以使用类对象来执行此操作。从计算偏斜的函数开始:
case class
然后使用类对象创建它的实例:
def computeSkew(value1: Int, value2: Int) =
if (value1 == 500 && value2 == 700) 0 else Random.nextInt()
另一种选择是通过扩展case class MyClass1 private(value1: Int, value2: Int, skew: Int)
object MyClass1 {
def apply(value1: Int, value2: Int): MyClass1 =
MyClass1(value1, value2, computeSkew(value1, value2))
}
类来添加字段,但是具有相同Skew
和value1
的对象将始终比较相等,因为value2
不会包含在skew
测试中。
如评论中所述,我不确定将equals
添加到核心数据对象是否是解决重复问题的正确方法。最好在表中使用时将偏斜包装在对象周围,并保持原始数据不变。
一个简单的包装看起来像这样:
skew
然后在表中使用case class WithSkew[T] private(data: T, skew: Int)
object WithSkew {
def apply[T](data: T): WithSkew[T] =
WithSkew(data, Random.nextInt())
}
val x = MyClass1(500, 700)
val xSkew = WithSkew(x)
避免重复,并在再次从表中取出行时提取xSkew
字段。
以前的版本不基于data
和value1
执行自定义偏斜计算。这可以通过引入类型类来解决,以提供特定类的偏斜计算:
value2
除非该类存在trait HasSkew[T] {
def skew(instance: T): Int
}
case class DefaultSkew[T]() extends HasSkew[T] {
def skew(instance: T): Int = Random.nextInt()
}
object HasSkew {
implicit object skew1 extends HasSkew[MyClass1] {
def skew(data: MyClass1): Int =
computeSkew(data.value1, data.value2)
}
}
case class WithSkew[T] private(data: T, skew: Int)
object WithSkew {
def apply[T](data: T)(implicit sk: HasSkew[T] = DefaultSkew[T]()): WithSkew[T] =
WithSkew(data, sk.skew(data))
}
的隐式实例,否则WithSkew
包装器将使用DefaultSkew
中的偏斜计算。
此版本具有更多样板代码,但是它将允许使用HasSkew
值包装任何类,并且可以根据需要为每个特定类量身定制偏斜计算。
答案 2 :(得分:0)
我不确定您要在这里找到什么,但是根据您的描述,这就是我得到的:
class SkewedClass(values: Int*) {
lazy val skew: Int = {
values.sum * 1234
}
}
case class MyClass1(value1: Int, value2: Int) extends SkewedClass(value1, value2)
case class MyClass2(value1: Int, value2: Int, value3: Int) extends SkewedClass(value1, value2, value3)
用您想使用的任何复杂函数替换偏斜实现。
答案 3 :(得分:0)
如果要隐藏倾斜的实现细节,可以使用自定义类型的scala。
trait SkewTrait {
def skew: Int
}
// package MyClass1
sealed class SkewClass1(value1: Int, value2: Int) {
this: SkewTrait =>
override def skew: Int = if (value1 == 500 && value2 == 700) 3 else 0
}
case class MyClass1(value1:Int, value2: Int) extends SkewClass1(value1, value2) with SkewTrait
// package MyClass2
sealed class SkewClass2(value1: Int) {
this: SkewTrait =>
override def skew: Int = if (value1 == 300) 4 else 0
}
case class MyClass2(value1: Int, value2: Int) extends SkewClass2(value1) with SkewTrait
println(MyClass1(1,2).skew)
println(MyClass2(300,5).skew)
结果:
0
4