Во первых - вам нет необходимости хранить все перестановки в памяти компьютера. Их можно скидывать на диск, сразу после генерации. Но не факт.
Во вторых - возможно, вам нужен алгоритм Нарайны.
В третьих - далеко не везде нужен ArrayList. Во многих ситуациях вы можете обойтись массивом фиксированной длины. Например, для хранения текущей перестановки.
В четвертых - если у вас так много генерируется перестановок - есть шанс, что они и в хэшсет не влезут. Думается мне, вам стоит задуматься о сортировке и фильтрации во внешней памяти.
В пятых - существуют ли ограничения по используемой памяти и общему времени работы?
В шестых - если вы воспользуетесь алгоритмом Нарайны - вы сможете сэкономить память на хранение результата в некоторых случаях. Подсказка - посмотрите на мультимножество вида {1^10, 2^1} с 11 неуникальными и двумя уникальными перестановками и предположите, сколько из этих перестановок будут храниться в HashSet.
P.S.: А язык вывода у вас украинский или белорусский? Слово "мультимножина" стоит запомнить. Кроме того, вам нет необходимости использовать printf, там, где достаточно написать println(s). А вот там, где printf пригодился бы - вы используете println. Сравните со своим кодом.
String s = "----------------------------------------";
System.out.println(s);
System.out.printf("Всього можливих комбінацій: %d ",count);
System.out.println(s);
long timeSpent = System.currentTimeMillis() - startTime;
System.out.printf("програма виконувадась %f секунд", (timeSpent*10e-6));