Можно создать решение Stream, которое не должно хранить в памяти все строки результатов, например,
public static Stream<String> perms(String str) {
if(str.length() <= 1) return Stream.of(str);
return IntStream.range(0, str.length()).boxed()
.flatMap(ix -> perms(new StringBuilder(str).deleteCharAt(ix).toString())
.map(s -> str.charAt(ix) + s));
}
Шаг рекурсии был заменен шагом flatMap
, который будет вычисляться лениво. .
Конечно, материализуется ли это преимущество, зависит от операции терминала, которую вы связываете с потоком. Например, когда вы цепляете toArray()
, вы вернетесь на круги своя. Но объединение в цепочку .forEach(System.out::println)
будет печатать перестановки без необходимости хранить их все в памяти. String
), мы можем опустить операцию toString
на промежуточном этапе и передать StringBuilder
напрямую. Таким образом, мы одновременно повышаем гибкость метода и производительность.
public static Stream<String> perms(CharSequence str) {
if(str.length() <= 1) return Stream.of(str.toString());
return IntStream.range(0, str.length()).boxed()
.flatMap(ix -> perms(new StringBuilder(str).deleteCharAt(ix))
.map(s -> str.charAt(ix)+s));
}