#java #apache-spark #generics #parameterized-class
#java #apache-spark #общие #параметризованный класс
Вопрос:
Я всегда сомневался, возможно ли наличие набора данных параметризованного / универсального класса в Java. Чтобы было более понятно, чего я хочу достичь, это что-то вроде этого:
Dataset<MyClass<Integer>> myClassInteger;
Dataset<MyClass<String>> myClassString;
Пожалуйста, дайте мне знать, если это возможно. Если бы вы также могли показать мне, как этого добиться, я был бы очень признателен. Спасибо!
Ответ №1:
Извините, этот вопрос устарел, но я хотел бы записать некоторые заметки, поскольку я смог работать с универсальными / параметризованными классами для наборов данных в Java, создав универсальный класс, который принимал параметр типа, а затем помещал методы внутри этого параметризованного класса. Т.е., class MyClassProcessor<T1>
где T1 может быть Integer
или String
.
К сожалению, в этом случае вы не сможете воспользоваться всеми преимуществами универсальных типов, и вам придется выполнить некоторые обходные пути:
- Мне пришлось использовать
Encoders.kryo()
, иначе универсальные типы сталиObject
с некоторыми операциями и не могли быть правильно приведены к универсальному типу.- Это приводит к некоторым другим неприятностям, т. Е. Не может присоединиться. Мне пришлось использовать трюки, такие как использование кортежей, чтобы разрешить некоторые операции объединения.
- Я не пробовал читать универсальные типы, мои параметризованные классы были введены позже с помощью
map
. Например, я прочиталTypeA
и позже работал с Dataset<MyClass>. - Я смог использовать более сложные пользовательские типы в общих чертах, а не только целое число, строку и т.д…
- Были некоторые раздражающие детали, такие как необходимость передавать литералы класса, т. Е.
TypeA.class
И использование необработанных типов для определенных функций карты и т.д…
Ответ №2:
Да, у вас может быть набор данных вашего собственного класса. Это выглядело бы как Dataset<MyOwnClass>
В приведенном ниже коде я попытался прочитать содержимое файла и поместить его в набор данных класса, который мы создали. Пожалуйста, проверьте фрагмент ниже.
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Encoder;
import org.apache.spark.sql.Encoders;
import org.apache.spark.sql.SparkSession;
import java.io.Serializable;
public class FileDataset {
public static class Employee implements Serializable {
public int key;
public int value;
}
public static void main(String[] args) {
// configure spark
SparkSession spark = SparkSession
.builder()
.appName("Reading JSON File into DataSet")
.master("local[2]")
.getOrCreate();
final Encoder<Employee> employeeEncoder = Encoders.bean(Employee.class);
final String jsonPath = "/Users/ajaychoudhary/Documents/student.txt";
// read JSON file to Dataset
Dataset<Employee> ds = spark.read()
.json(jsonPath)
.as(employeeEncoder);
ds.show();
}
}
Содержимое моего student.txt
файла
{ "key": 1, "value": 2 }
{ "key": 3, "value": 4 }
{ "key": 5, "value": 6 }
Он выдает следующий вывод на консоль:
--- -----
|key|value|
--- -----
| 1| 2|
| 3| 4|
| 5| 6|
--- -----
Я надеюсь, что это дает вам первоначальное представление о том, как вы можете иметь набор данных вашего собственного пользовательского класса.
Комментарии:
1. Я знаю, что у меня может быть набор данных моего собственного класса. Вопрос был в том, можете ли вы иметь набор данных параметризованного / универсального класса. Например, предположим, что ваш класс employee имеет поле «IDNumber», которое может быть любого типа String of Long. В этом случае вы можете параметризовать класс следующим образом: class Employee<T> {}. Впоследствии вы можете объявлять объекты в зависимости от ваших потребностей. Например. Employee<Long> employee1 = новый сотрудник <> (1,2,3L); Employee<String> employee2 = новый сотрудник<> (1,2, «A1B2C3»);. Пожалуйста, скажите мне, ясно ли я выразился.
2. Это требование не очень понятно из вопроса. Или я не получил его таким образом. Пожалуйста, отредактируйте свой вопрос с примером. Кто-нибудь может помочь с этим. Я не знаю, как это сделать.