Java Generics - вложенный цикл foreach, удаление дублирования кода - PullRequest
0 голосов
/ 18 ноября 2018

Я пытаюсь удалить некоторые дубликаты из моего кода и тем самым углубить моё понимание Java Generics.

Следующий фрагмент кода содержится в классе универсального типа:

ContainerClass<S1,S2,A>  

В одной из функций этого класса я столкнулся с необходимостью перебрать два набора следующим образом:

for (SomeClass<S1,A> t1 : set1) {
    logic.setT1(t1);
    if(set2.isEmpty()) {
        logic.apply();
    } else {
        for(SomeClass<S2,A> t2 : set2) {
            logic.setT2(t2);
            logic.apply();
        }
    }
}

logic это просто какой-то класс.

Логика методов требует еще одной итерации:

for(SomeClass<S2,A> t2 : set2) {
    logic.setT2(t2);
    if(set1.isEmpty()) {
        logic.apply();
    } else {
        for (SomeClass<S1,A> t1 : set1) {
            logic.setT1(t1);
            logic.apply();
        }
    }
}

У меня возникли проблемы с созданием метода, который мог бы обрабатывать оба случая для вызовов аргументов.

Любая помощь будет принята с благодарностью,
Заранее спасибо.

По запросу, следующий класс Logic (внутренний класс):

private class Logic
{
    private Pair<S1,S2> currState;
    private Optional<Transition<S1,A>> t1;
    private Optional<Transition<S2,A>> t2;

    Logic()
    {
        init();
    }

    void setCurrState(Pair<S1,S2> currState)
    {
        this.currState = currState;
    }

    void setT1(Transition<S1,A> t1)
    {
        this.t1 = Optional.of(t1);
    }

    void setT2(Transition<S2,A> t2)
    {
        this.t2 = Optional.of(t2);
    }

    void apply()
    {
        if(t1.isPresent() && t2.isPresent()) {
            handleBoth();
        } else {
            handleSingle();
        }
        init();
    }

    private void add(Pair<S1,S2> to, A action)
    {
        if (!res.getStates().contains(to)){
            toReach.add(to);
            res.addState(to);
        }
        res.addAction(action);
        res.addTransition(new Transition<>(currState,action,to));
    }

    private void handleBoth()
    {
        var _t1 = t1.get();
        var _t2 = t2.get();

        if (_t1.getAction().equals(_t2.getAction()) && handshake.contains(_t1.getAction())) {
            add(Pair.pair(_t1.getTo(), _t2.getTo()), _t1.getAction());
        } else {
            handleSingle();
        }
    }

    private void handleSingle()
    {
        t1.ifPresent(_t1 -> {
            if(!handshake.contains(_t1.getAction())) 
                add(Pair.pair(_t1.getTo(),currState.second),_t1.getAction());
        });
        t2.ifPresent(_t2 -> {
            if (!handshake.contains(_t2.getAction()))
                add(Pair.pair(currState.first,_t2.getTo()),_t2.getAction());
        });
    }

    private void init()
    {
        t1 = Optional.empty();
        t2 = Optional.empty();
    }
}

1 Ответ

0 голосов
/ 18 ноября 2018

Звучит так, как будто вы хотите добавить некоторые дополнительные шаблоны к Logic, чтобы сделать его Logic<S1, S2, A>, независимо от класса включения.Исходя из того, что вы показываете, логика является симметричной и достаточно не сохраняющей состояния, поэтому вы можете добавить следующий метод к Container:

public void <X1, X2> doTheThing(X1 set1, X2 set2)
{
    Logic logic = new Logic<X1, X2, A>();
    for (SomeClass<X1, A> t1 : set1) {
        logic.setT1(t1);
        if(set2.isEmpty())
            logic.apply();
        else
            for (SomeClass<S2,A> t2 : set2) {
                logic.setT2(t2);
                logic.apply();
            }
    }
}

Теперь вы можете вызывать его с помощью doTheThing(set1, set2) и doTheThing(set2, set1).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...