Используя битовые манипуляции, мы можем легко перебирать все комбинации строк из массива строк.
Например, если у нас есть 3 строки ("a1"
, "a2"
, "a3"
) , мы будем повторять от 1 до 7 (2³-1). В двоичном представлении этого числа каждый бит справа указывает, включена ли эта входная строка в результат. идет справа от -->
. Назовем это значением результат .
Например, если мы сейчас генерируем результат для "a2"
(индекс результата 1), мы «вытаскиваем» его из пула битов. , так что теперь у нас есть только 2 бита. Любой бит в индексе результата или после него представляет индекс значения, на единицу превышающий битовый индекс.
Это означает, что бит 0 является индексом значения 0, а бит 1 - индексом значения 2.
01 "a1"
10 "a3"
11 "a1", "a3"
Теперь мы можем написать код следующим образом:
static void printCombinations(String... values) {
if (values.length < 2 || values.length > 30)
throw new IllegalArgumentException("There must be between 2 and 30 values (got " + values.length + ")");
if (values.length != new HashSet<>(Arrays.asList(values)).size())
throw new IllegalArgumentException("Duplicate values not allowed");
final int maxBit = values.length - 1;
final int maxMask = 1 << maxBit;
StringBuilder buf = new StringBuilder();
for (int resIdx = 0; resIdx < values.length; resIdx++) {
for (int bitMask = 1; bitMask < maxMask; bitMask++) {
buf.setLength(0);
for (int bitIdx = 0; bitIdx < maxBit; bitIdx++)
if ((bitMask & (1 << bitIdx)) != 0)
buf.append(',').append(values[bitIdx >= resIdx ? bitIdx + 1 : bitIdx]);
System.out.println(buf.append("-->").append(values[resIdx]).substring(1));
}
}
}
Тест
printCombinations("a1", "a2", "a3", "a4");
Вывод
a2-->a1
a3-->a1
a2,a3-->a1
a4-->a1
a2,a4-->a1
a3,a4-->a1
a2,a3,a4-->a1
a1-->a2
a3-->a2
a1,a3-->a2
a4-->a2
a1,a4-->a2
a3,a4-->a2
a1,a3,a4-->a2
a1-->a3
a2-->a3
a1,a2-->a3
a4-->a3
a1,a4-->a3
a2,a4-->a3
a1,a2,a4-->a3
a1-->a4
a2-->a4
a1,a2-->a4
a3-->a4
a1,a3-->a4
a2,a3-->a4
a1,a2,a3-->a4