Проблема в том, что вы делаете очень много в этом цикле, а не разделяете функциональность на простые методы.
Если вы хотите придерживаться процедурного подхода, вы можете переместить чтение размера массива и k в отдельные методы и использовать тот факт, что результатом присваивания является присвоенное значение:
for (int arraySize; ( arraySize = readArraySize ( input ) ) != -1;) {
final int k = readKthSmallestElement ( input );
List<Integer> randomData = generateRandomData(arraySize, 1, 100);
quickSelect(randomData, k);
}
Однако это все-таки немного уродливо и плохо инкапсулировано. Поэтому вместо двух != -1
тестов для отдельных переменных инкапсулируйте arraySize
, k
и randomData
в объекте и создайте метод, который считывает данные из ввода и возвращает либо объект QuickSelect
или null
, если пользователь выходит:
for ( QuickSelect select; ( select = readQuickSelect ( input ) ) != null; ) {
select.generateRandomData();
select.quickSelect();
}
Возможно, вы даже захотите перейти к следующему этапу создания последовательности объектов QuickSelect из входных данных, каждый из которых инкапсулирует данные за одну итерацию:
for ( QuickSelect select : new QuickSelectReader ( input ) ) {
select.generateRandomData();
select.quickSelect();
}
где QuickSelectReader реализует Iterable, а итератор имеет логику для создания объекта QuickSelect, который инкапсулирует arraySize, k, список и операцию быстрого выбора. Но в итоге получается гораздо больше кода, чем процедурных вариантов.
Я бы сделал это, только если бы хотел использовать его где-то еще; это не стоит усилий, чтобы сделать main () красивым.
Также обратите внимание, что "-1"
не соответствует регулярному выражению "\\d+"
, поэтому у вас действительно есть бесконечный цикл.