Цикл for будет более эффективным, поскольку нет необходимости использовать вызовы метода. (Как правило, циклы почти всегда более эффективны, чем рекурсия)
Чтобы объяснить, почему вы должны вдаваться в подробности того, что происходит, когда вы вызываете метод и что-то, называемое стек вызовов .
В основном, когда вы вызываете метод, ему нужно немного места для работы (для таких вещей, как его локальные переменные и т. Д.), Ему также нужно место для входящих параметров, передаваемых ему, и место для хранения адреса возврата, где он должен идти, когда это сделано, выполняя. Это пространство динамически обеспечивается путем «помещения» значений в стек. Это пространство стека остается занятым до тех пор, пока метод не вернется, и в этот момент он «вытолкнут».
Итак, подумайте о рекурсии в этом контексте: каждый раз, когда вы вызываете метод изнутри себя, вы помещаете больше данных в стек, не возвращаясь из метода, в котором вы были (и, таким образом, не освобождая пространство стека, которое занимал вызывающий метод) ). По мере углубления вашей рекурсии количество памяти увеличивается.
В отличие от написанного вами цикла for, используется только фиксированный объем памяти, предоставляемый одним нажатием фрейма стека.