Java 检查RDD的相等性
我在JUnit中进行了一些测试,需要检查两个Spark RDD的相等性 我想到的一种方法是:Java 检查RDD的相等性,java,junit,equals,apache-spark,Java,Junit,Equals,Apache Spark,我在JUnit中进行了一些测试,需要检查两个Spark RDD的相等性 我想到的一种方法是: JavaRDD<SomeClass> expResult = ...; JavaRDD<SomeClass> result = ...; assertEquals(expResult.collect(), result.collect()); javarddexpresult=。。。; JavaRDD结果=。。。; assertEquals(expResult.collect
JavaRDD<SomeClass> expResult = ...;
JavaRDD<SomeClass> result = ...;
assertEquals(expResult.collect(), result.collect());
javarddexpresult=。。。;
JavaRDD结果=。。。;
assertEquals(expResult.collect(),result.collect());
有比这更好的方法吗?如果预期结果相当小,最好
收集
RDD数据并在本地进行比较(就像您编写的那样)
当需要在测试中使用足够大的数据集时,几乎没有其他可能性:
免责声明:我对Spark Java API不够熟悉,因此我将用Scala编写进一步的示例代码。我希望这不会是一个问题,因为它可以用Java重写,或者转换成几个从Java代码调用的实用函数
方法1:将RDD压缩在一起并逐项比较
只有在RDD中元素的顺序定义良好(即RDD已排序)的情况下,此方法才可用
diff
阵列将包含多达100个微分对。如果RDD足够大,并且您希望从diff
本地获取所有项目,那么可以使用ToLocalWriter
方法。最好不要使用collect
方法,因为您可能会运行OOM
这种方法可能是最快的,因为它不需要洗牌,但只有在RDD中的分区顺序和分区中的项目顺序定义良好的情况下,才可以使用这种方法
方法2:联合组RDD
此方法可用于测试结果
RDD是否包含指定的(可能是非唯一的)值,而没有任何特定顺序
val diff = expResult.map(_ -> 1)
.cogroup(result.map(_ -> 1))
.collect { case (a, (i1, i2)) if i1.sum != i2.sum => a -> (i1.sum - i2.sum) }
.take(100)
diff
数组将包含差异值以及金额之间的差异
例如:
- 如果
包含某个值的单个实例,而expResult
不包含该值,则数字将为result
李>+1
- 如果
包含另一个值的3个实例,并且result
仅为1,则该数字将为expResult
-2
此方法将比其他选项(即相互减去RDD)更快,因为它只需要一次洗牌。在我的例子中,使用Spark转换为Java时,仅使用collect方法不起作用。assertEquals的结果总是错误的 所以这个测试:
assertEquals(
this.fooExpectedRddTest.collect(),
this.fooServiceTest.getRdd().collect()
);
生成此结果:
FooServiceTest.getRdd:143 expected:
scala.collection.convert.Wrappers$SeqWrapper<[
{"a":1,"b":2,"c":1496405614},
{"a":1,"b":3,"c":1496243614},
{"a":2,"b":2,"c":1496416414}
]>
but was:
scala.collection.convert.Wrappers$SeqWrapper<[
{"a":1,"b":2,"c":1496405614},
{"a":1,"b":3,"c":1496243614},
{"a":2,"b":2,"c":1496416414}
]>
FooServiceTest.getRdd:143预期值:
scala.collection.convert.Wrappers$SeqWrapper
但是:
scala.collection.convert.Wrappers$SeqWrapper
我处理这个问题的方法是把它们转换成更容易比较的东西
List<Tuple3<Integer,Integer,Double>> expectedList = this.fooExpectedRddTest.map(
(Foo foo) -> {
return new Tuple3<Integer,Integer,Double>(
foo.getA(),
foo.getB(),
foo.getC()
);
}
).collect();
List<Tuple3<Integer,Integer,Double>> receivedList = this.fooServiceTest.getRdd().map(
(Foo foo) -> {
return new Tuple3<Integer,Integer,Double>(
foo.getA(),
foo.getB(),
foo.getC()
);
}
).collect();
assertEquals(
expectedList,
receivedList
);
List expectedList=this.fooExpectedRDTest.map(
(福福)->{
返回新的Tuple3(
foo.getA(),
foo.getB(),
foo.getC()
);
}
).收集();
List receivedList=this.fooServiceTest.getRdd().map(
(福福)->{
返回新的Tuple3(
foo.getA(),
foo.getB(),
foo.getC()
);
}
).收集();
资产质量(
预期名单,
接收列表
);
我想现在我将继续使用collect()
方法,因为我的数据非常小(尽管是result.collect().removeAll(expResult.collect())
的形式,然后断言result
为空,因为我发现这是检查两个列表是否相等的更好方法)。知道我未来的选择是非常好的,尽管我会退回更大的收藏品。
List<Tuple3<Integer,Integer,Double>> expectedList = this.fooExpectedRddTest.map(
(Foo foo) -> {
return new Tuple3<Integer,Integer,Double>(
foo.getA(),
foo.getB(),
foo.getC()
);
}
).collect();
List<Tuple3<Integer,Integer,Double>> receivedList = this.fooServiceTest.getRdd().map(
(Foo foo) -> {
return new Tuple3<Integer,Integer,Double>(
foo.getA(),
foo.getB(),
foo.getC()
);
}
).collect();
assertEquals(
expectedList,
receivedList
);