Un peu de contexte: j'analyse un grand livre comptable qui a account1 et account2 comme types int. Chacun est un nombre dans la plage [0, 99999]. J'ai de nombreuses combinaisons à considérer.

Idéalement, j'aimerais utiliser quelque chose comme

switch (account1, account2){
    case (1,1):
        /*account1 is 1, account2 is 1*/
    case (2,1):
        /*account1 is 2, account2 is 1*/
}

Etc. (Je n'ai besoin que de considérer environ 20 combinaisons possibles).

Existe-t-il un moyen d'y parvenir en Java?

J'ai examiné cette question Stockage de paires de numéros en java

Et pourrait créer une classe IntPair. Peut-être que si je définis bool equals, je pourrais switch sur une instance, de la même manière que vous pouvez activer java.lang.String.

3
Michael Bullock 24 janv. 2017 à 17:44

4 réponses

Meilleure réponse

Hélas, ce n'est pas possible en Java. Vous ne pouvez activer que les types intégraux, ou a java.lang.String à partir de la version 7 de Java (vous ne pouvez pas intégrer cette fonctionnalité dans votre propre type en remplaçant equals et {{X2 }} de java.lang.Object).

Mais cela pourrait vous inciter à faire un hack:

switch (Integer.toString(account1) + "_" + Integer.toString(account2)){
    case "1_1":
    case "2_1":    
}

Je trouve cela étonnamment lisible.

9
Bathsheba 24 janv. 2017 à 14:53

Une stratégie possible est comme celle-ci, une légère variation de la réponse de @ Morgan:

public enum AccountRelationship {
    BOSS_ACCOUNTS,
    SECRET_SWISS_TAX_AVOIDING_ACCOUNTS,
    OTHER;
}

public static final Map<AccountPair,AccountRelationship> relationships = new HashMap<>();
static {
    relationships.put(new AccountPair(1,1),AccountRelationship.BOSS_ACCOUNTS);
    relationships.put(new AccountPair(1,5),AccountRelationship.BOSS_ACCOUNTS);
    relationships.put(new AccountPair(2,2),AccountRelationship.SECRET_SWISS_TAX_AVOIDING_ACCOUNTS);
}

public void doSomething(AccountPair pair) {
    AccountRelationship rel = relationships.getOrDefault(pair, AccountRelationship.OTHER);
    switch (rel) {
    case BOSS_ACCOUNTS: receiveLotsOfBonus(); break;
    case SECRET_SWISS_TAX_AVOIDING_ACCOUNTS: laughAllTheWayToTheBank(); break;
    case OTHER: payLotsOfTaxes();
    }
}

Cela sépare la logique de déterminer ce qu'il faut faire de l'appel des actions, ce qui rend les choses beaucoup plus lisibles et plus faciles à étendre. Sans oublier que vous pouvez facilement tout tester séparément.

Comme vous pouvez le voir, c'est assez verbeux.

Il y a un autre piège potentiel: la carte relationships. C'est très bien si vous avez plusieurs paires de comptes qui nécessitent la même action, mais lorsque vous ajoutez une nouvelle valeur à AccountRelationship, il est facile d'oublier également de mettre à jour cette carte.

0
biziclop 24 janv. 2017 à 15:48

Juste pour le plaisir d'utiliser des nombres premiers: (c'est sûr dans la plage mentionnée, mais sur les nombres entiers élevés, cela échouera sûrement)

Le calcul de cas sera effectué au moment de la compilation.

public class Switch {

    public static void main(String[] args) {
        int i = 1;
        int j = 2;
        switch (i * 2 + j * 3) {
        case 1 * 2 + 2 * 3:
            System.out.println("match");
        }
    }
}
0
Turo 25 févr. 2019 à 12:50

ÉDITER :

Peut être ça ?

public enum Account{

    ACC_512_401(512,401), 
    ACC_512_402(512,402);

    private final int accA;
    private final int accB;

    Account(int accA, int accB){
        this.accA=accA;
        this.accB=accB;
    }

    private int getAccA(){
        return accA;
    }
    private int getAccB(){
        return accB;
    }
    public static Account getEnum(int accA, int accB){
        for(Account acc : values()){
            if(accA == acc.getAccA() && accB == acc.getAccB()){
                return acc;
            }
        }
        return null;
    }
}



public class testswitch {
    public static void main(String[] args) {
        test(Account.getEnum(512, 401));
    }

    public static void test(Account acc){

        switch (acc){
        case ACC_512_401:
            System.out.println("A");
            break;
        case ACC_512_402:
            System.out.println("A");
            break;
            default:
                break;
        }
    }
}

Vous faites votre changement sur votre énumération.

EDIT: J'ai ajouté la méthode getEnum pour obtenir la valeur de l'entrée int. Maintenant c'est ce que tu veux je suppose.

4
Morgan 24 janv. 2017 à 15:31