Я думаю, что вы можете искать функции окна: http://spark.apache.org/docs/latest/api/python/pyspark.sql.html?highlight=window#pyspark.sql. Окно
https://databricks.com/blog/2015/07/15/introducing-window-functions-in-spark-sql.html
Вот пример в Scala (теперь у меня нет Spark Shell с Hive, поэтому я не смог проверить код, но я думаю, что он должен работать):
case class MyRow(name: String, id_sa: String, id_sb: String)
val myDF = sc.parallelize(Array(
MyRow("n1", "a1", "b1"),
MyRow("n2", "a1", "b2"),
MyRow("n3", "a1", "b2"),
MyRow("n1", "a2", "b2")
)).toDF("name", "id_sa", "id_sb")
import org.apache.spark.sql.expressions.Window
val windowSpec = Window.partitionBy(myDF("id_sa")).orderBy(myDF("id_sb").desc)
myDF.withColumn("max_id_b", first(myDF("id_sb")).over(windowSpec).as("max_id_sb")).filter("id_sb = max_id_sb")
Вероятно, есть более эффективные способы достижения тех же результатов с помощью функций Window, но я надеюсь, что это указывает на правильное направление.
Я нашел эту ссылку, показывающую, как вы можете выполнить модульное тестирование объекта, подлежащего продаже:
Вы можете на самом деле пропустить Bundle
, если вам действительно не нужно включать его, как это сделал Зорх. Затем вы получите что-то вроде этого:
public void testTestClassParcelable(){
TestClass test = new TestClass();
// Obtain a Parcel object and write the parcelable object to it:
Parcel parcel = Parcel.obtain();
test.writeToParcel(parcel, 0);
// After you're done with writing, you need to reset the parcel for reading:
parcel.setDataPosition(0);
// Reconstruct object from parcel and asserts:
TestClass createdFromParcel = TestClass.CREATOR.createFromParcel(parcel);
assertEquals(test, createdFromParcel);
}
Вы можете сделать это следующим образом:
//Create parcelable object and put to Bundle
Question q = new Question(questionId, surveyServerId, title, type, answers);
Bundle b = new Bundle();
b.putParcelable("someTag", q);
//Save bundle to parcel
Parcel parcel = Parcel.obtain();
b.writeToParcel(parcel, 0);
//Extract bundle from parcel
parcel.setDataPosition(0);
Bundle b2 = parcel.readBundle();
b2.setClassLoader(Question.class.getClassLoader());
Question q2 = b2.getParcelable("someTag");
//Check that objects are not same and test that objects are equal
assertFalse("Bundle is the same", b2 == b);
assertFalse("Question is the same", q2 == q);
assertTrue("Questions aren't equal", q2.equals(q));
Я использую класс помощника посылки для преобразования объекта в / из участка.
См. Эту суть: https://gist.github.com/scallacs/f749a7385bcf75829a98d7b651efd02e
Использование очень просто:
Model model = new Model("HelloWorld");
// Create an object from the parcel model
Model createdFromParcel = ParcelTestHelper.createFromParcel(model, model.CREATOR);
// Do your assertions...
assertEquals(model.value, createdFromParcel.value);
Реализация:
import android.os.Parcel;
import android.os.Parcelable;
public class ParcelTestHelper {
public static String DEFAULT_CREATOR_FIELD = "CREATOR";
public static <T extends Parcelable> T createFromParcel(T input, Parcelable.Creator<T> creator) {
Parcel parcel = toParcel(input);
return fromParcel(parcel, creator);
}
public static <T extends Parcelable> T createFromParcel(T input) throws NoSuchFieldException, IllegalAccessException {
return createFromParcel(input, getCreator(input));
}
public static <T extends Parcelable> Parcel toParcel(T input) {
Parcel parcel = Parcel.obtain();
input.writeToParcel(parcel, input.describeContents());
parcel.setDataPosition(0);
return parcel;
}
public static <T> Parcelable.Creator<T> getCreator(T input) throws NoSuchFieldException, IllegalAccessException {
return getCreator(input, DEFAULT_CREATOR_FIELD);
}
public static <T> Parcelable.Creator<T> getCreator(T input, String field) throws NoSuchFieldException, IllegalAccessException {
Object creator = input.getClass().getField(field).get(input);
if (!(creator instanceof Parcelable.Creator)) {
throw new InternalError("Should have field " + field + " instance of Parcelable.Creator");
}
return (Parcelable.Creator<T>) creator;
}
public static <T extends Parcelable> T fromParcel(Parcel parcel, Parcelable.Creator<T> creator) {
return creator.createFromParcel(parcel);
}
}
Так как этот вопрос и ответы помогли мне несколько лет спустя, я подумал, что добавлю свое собственное предложение, которое будет заключаться в assert
, что dataPosition()
в конце чтения был таким же, как в конец записи. Опираясь на ответ Xilconic :
@Test
public void testTestClassParcelable(){
TestClass test = new TestClass();
// Obtain a Parcel object and write the parcelable object to it:
Parcel parcel = Parcel.obtain();
test.writeToParcel(parcel, 0);
//>>>>> Record dataPosition
int eop = parcel.dataPosition();
// After you're done with writing, you need to reset the parcel for reading:
parcel.setDataPosition(0);
// Reconstruct object from parcel and asserts:
TestClass createdFromParcel = TestClass.CREATOR.createFromParcel(parcel);
assertEquals(test, createdFromParcel);
//>>>>> Verify dataPosition
assertEquals(eop, parcel.dataPosition());
}
Справочная информация: Это пришло ко мне после того, как я потратил (смущающее) количество времени на отладку плохого Parcelable
, В моем случае writeToParcel
записывал дублирующееся поле из одного объекта в графе объекта средней сложности. Поэтому последующие объекты были прочитаны неправильно, давая ложные исключения, и не было ошибок при тестировании с конкретным плохо себя ведущим объектом.
Было трудно отследить, и тогда я понял, что проверка dataPosition
могла бы точно определить проблему, поскольку у меня есть тесты на внутренних объектах, а также на основном контейнере.
Kotlin: Так как я работаю в Kotlin, немного лямбда и магии reifying:
class ParcelWrap<T>(val value: T)
val <T> T.parcel: ParcelWrap<T> get() = ParcelWrap(this)
inline fun <reified T: Parcelable> ParcelWrap<T>.test(
flags: Int = 0,
classLoader: ClassLoader = T::class.java.classLoader,
checks: (T) -> Unit
): T {
// Create the parcel
val parcel: Parcel = Parcel.obtain()
parcel.writeParcelable(this.value, flags)
// Record dataPosition
val eop = parcel.dataPosition()
// Reset the parcel
parcel.setDataPosition(0)
// Read from the parcel
val newObject = parcel.readParcelable<T>(classLoader)
// Perform the checks provided in the lambda
checks(newObject)
// Verify dataPosition
assertEquals("writeToParcel wrote too much data or read didn't finish reading", eop, parcel.dataPosition())
return newObject
}
Теперь я могу очень легко проверить по этим направлениям, если есть полный и надежный equals()
:
testObject.parcel.test { assertEquals(testObject, it) }
Обратите внимание, что .parcel.test
избегает необходимости переопределять параметр универсального типа, используя этот ответ .
Или, для более сложных утверждений:
testObject.parcel.test {
assertEquals(123, it.id)
assertEquals("dewey", it.name)
// ...
}