#java #arrays #algorithm #apache-spark #recursion
Вопрос:
Я хочу рекурсивно разделить набор данных в соответствии с одним из его атрибутов ( attVal
) и на основе значений атрибутов других наборов данных, таких как следующие: Учитывая исходный набор ds1
данных и наборы данных для разделения ds2
, ds3
,…, я хочу разделить на min(df2)
и max(df2)
, min(df3)
и max(df3)
… набор ds1
данных, подобный этому:
Split by min(df2) and max(df2):
min(df1)-----------------------------------------------max(df1)
min(df2)----------------max(df2)
Или разделить на max(df2)
:
min(df1)----------------------------------max(df1)
min(df2)------------------------------------max(df2)
Разделить на min(df2)
:
min(df1)------------------------------------max(df1)
min(df2)----------------------------------max(df2)
Следующим разделением будет использование разделенной части предыдущего шага и min(df3) amp; min(df3)
значений (и т. Д. Для следующих шагов с использованием ds4
…). А затем верните все полученные детали.
Для этой цели я создал следующий метод Java :
public static ArrayList<Dataset<Row>> mySplittingMethod(Dataset<Row> df1, ArrayList<Dataset<Row>> allSplittingDf) {
ArrayList<Dataset<Row>> partsOfSplits = null;
long df1Max = df1.select(max(df1.col("attVal"))).first().getLong(0);
long df1Min = df1.select(min(df1.col("attVal"))).first().getLong(0);
for (Dataset<Row> currentDf : allSplittingDf) {
df2 = currentDf;
long df2Max = df2.select(max(df2.col("attVal"))).first().getLong(0);
long df2Min = df2.select(min(df2.col("attVal"))).first().getLong(0);
if (df1Min < df2Min amp;amp; df2Min < df1Max amp;amp; df1Max < df2Max) {
Dataset<Row> firstDf = df1.where("attVal<= df2Min");
mySplittingMethod(firstDf, allSplittingDf);
Dataset<Row> secondDf = df1.where("attVal> df2Min");
mySplittingMethod(secondDf, allSplittingDf);
partsOfSplits.add(firstDf);
partsOfSplits.add(secondDf);
} else if (df1Min > df2Min amp;amp; df1Min < df2Max amp;amp; df2Max < df1Max) {
Dataset<Row> firstDf = df1.where("attVal<= df2Max");
mySplittingMethod(firstDf, allSplittingDf);
Dataset<Row> secondDf = df1.where("attVal> df2Max");
mySplittingMethod(secondDf, allSplittingDf);
partsOfSplits.add(firstDf);
partsOfSplits.add(secondDf);
} else if (df1Min > df2Min amp;amp; df2Max < df1Max) {
Dataset<Row> firstDf = df1.where("attVal<= df2Min");
mySplittingMethod(firstDf, allSplittingDf);
Dataset<Row> secondDf = df1.where("attVal>= df2Min amp;amp; attVal<= df2Max");
mySplittingMethod(secondDf, allSplittingDf);
Dataset<Row> thirdDf = df1.where("attVal> df2Max");
mySplittingMethod(thirdDf, allSplittingDf);
partsOfSplits.add(firstDf);
partsOfSplits.add(secondDf);
partsOfSplits.add(thirdDf);
} else continue;
}
return partsOfSplits;
}
Мой вопрос: для входного параметра больших размеров allSplittingDf
ошибка StackOverflow показывает, почему? С точки зрения алгоритма, что-то не так с моими рекурсивными вызовами?
Комментарии:
1. Каждый вызов рекурсивного метода сохраняет некоторые данные в памяти стека, поэтому многие уровни рекурсии приводят к исчерпанию памяти стека.
2. Каждый элемент в вашем «allSplittingDf» потенциально помещает новый элемент в стек Java. Этот стек ограничен (я думаю, 128 элементов), что означает, что если вы отправите массив «allSplittingDf», который производит более 128 вызовов, стек переполнится. Рекурсию следует использовать только тогда, когда глубина вызовов управляема / вы заранее знаете, что она будет соответствовать стандартному стеку. Для таких задач, где глубина неизвестна, лучше вместо этого использовать итерационное решение.
3. @MatteoNNZ не могли бы вы предложить итеративный подход в этом случае ?