Как избежать многократного повторения пустого кода?
Есть условно большой массив (несколько десятков тысяч элементов) и 3 коротких(0-5 элементов). Заранее количество элементов в коротких массивах неизвестно. Необходимо пошагово пройти по большому массиву и, если определенный короткий не пуст, запускать соответствующий ему метод, а если пуст метод не запускается. Схематически код на Java получился такой:
for (String sw: bigMass) {
if(!shortMass.isEmpty())
MethodOne();
if(!shortMass2.isEmpty())
MethodTwo();
if(!shortMass3.isEmpty())
MethodThree();
}
Все работает, но вот если какие-то из коротких массивов пустые - как избавится от проверки на каждом шаге? Нельзя ли после получения данных о коротких массивах спроектировать цикл так, чтобы не было ненужных опросов? Можно решить задачу с помощью фильтров, но тогда большой массив будет сканироваться неоднократно, пусть от фильтра к фильтру он и будет уменьшаться.
Ответы (2 шт):
- Можно вынести вычисление isEmpty за цикл, даст совершенно незначительную экономию, так как этот метод не тяжелый:
var sm1 = !shortMass.isEmpty();
var sm2 = !shortMass2.isEmpty();
var sm3 = !shortMass3.isEmpty();
for (String sw: bigMass) {
if(sm1)
MethodOne();
if(sm2)
MethodTwo();
if(sm3)
MethodThree();
}
- Можно сделать отдельные циклы для каждой из ситуаций получиться 6 блоков:
var sm1 = !shortMass.isEmpty();
var sm2 = !shortMass2.isEmpty();
var sm3 = !shortMass3.isEmpty();
if(sm1 && !sm2 && !sm3){
for (String sw: bigMass) {
MethodOne();
}
}
if(!sm1 && sm2 && !sm3){
for (String sw: bigMass) {
MethodTwo();
}
}
if(!sm1 && !sm2 && sm3){
for (String sw: bigMass) {
MethodThree();
}
}
if(sm1 && sm2 && !sm3){
for (String sw: bigMass) {
MethodOne();
MethodTwo();
}
}
if(!sm1 && sm2 && !sm3){
for (String sw: bigMass) {
MethodTwo();
MethodThree();
}
}
if(sm1 && !sm2 && sm3){
for (String sw: bigMass) {
MethodOne();
MethodThree();
}
}
if(sm1 && sm2 && sm3){
for (String sw: bigMass) {
MethodOne();
MethodTwo();
MethodThree();
}
}
Оптимальнее не куда, но читаемость приноситься в жертву.
Похоже вы пытаетесь оптимизировать, то что не требует оптимизации.
Создаёте "список" методов с учётом их сигнатур, который заполняется в зависимости от пустоты соответствующих массивов и вызываете каждый метод во вложенном цикле / при помощи forEach:
private List<Runnable> fillMethodList() {
List<Runnable> methods = new ArrayList<>();
if (!shortMass1.isEmpty()) methods.add(this::Method1);
if (!shortMass2.isEmpty()) methods.add(this::Method2);
if (!shortMass3.isEmpty()) methods.add(this::Method3);
return methods;
}
List<Runnable> methods = fillMethodList();
for (String sw: bigMass) {
methods.forEach(Runnable::run);
}
Если понадобится передавать параметр sw внутрь методов Method1(String s), следует использовать Consumer<String> вместо Runnable.
private List<Consumer<String>> fillConsumerList() {
List<Consumer<String>> methods = new ArrayList<>();
if (!shortMass1.isEmpty()) methods.add(this::consume1);
if (!shortMass2.isEmpty()) methods.add(this::consume2);
if (!shortMass3.isEmpty()) methods.add(this::consume3);
return methods;
}
List<Consumer<String>> methods = fillConsumerList();
String[] bigMass = {"a", "b"};
for (String sw: bigMass) {
methods.forEach(action -> action.accept(sw));
}