Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to condense large switch statements

I have a large switch like following:

public int procList(int prov, ArrayList<TXValue> txValueList, Context context)
{
    switch(prov)
    {
    case Foo.PROV_ONE:
        return proc_one(txValueList, context);

    case Foo.PROV_NOE:
        return proc_noe(txValueList, context);

    case Foo.PROV_BAR:
        return proc_bar(txValueList, context);

    case Foo.PROV_CABAR:
        return proc_cabar(txValueList, context);

    case Foo.PROV_FAR:
        return proc_far(txValueList, context);

    case Foo.PROV_TAR:
        return proc_tar(txValueList, context);

    case Foo.PROV_LBI:
        return 408;

    default:
        return -1;
    }
}

In c++ I can use std::map<Foo, some_function_ptr> and use it in manner as following:

map[prov](txValueList, context); 

There is not pointer to function in Java. However, it uses abstract classes like it is in the answer. So, is there a best way to eliminate huge switch clauses in java?

like image 476
Loom Avatar asked Jun 15 '15 15:06

Loom


2 Answers

What you're looking for is an enum.

public enum Prov {
    PROV_ONE(Foo.PROV_ONE) {
        @Override
        public int provMethod(List<TXValue> txValueList, Context context) {
            return proc_one(txValueList, context);
        }
    },
    PROV_NOE(Foo.PROV_NOE) {
        @Override
        public int provMethod(List<TXValue> txValueList, Context context) {
            return proc_noe(txValueList, context);
        }
    },
    PROV_BAR(Foo.PROV_BAR) {
        @Override
        public int provMethod(List<TXValue> txValueList, Context context) {
            return proc_bar(txValueList, context);
        }
    },
    PROV_CABAR(Foo.PROV_CABAR) {
        @Override
        public int provMethod(List<TXValue> txValueList, Context context) {
            return proc_cabar(txValueList, context);
        }
    },
    PROV_FAR(Foo.PROV_FAR) {
        @Override
        public int provMethod(List<TXValue> txValueList, Context context) {
            return proc_far(txValueList, context);
        }
    },
    PROV_TAR(Foo.PROV_TAR) {
        @Override
        public int provMethod(List<TXValue> txValueList, Context context) {
            return proc_tar(txValueList, context);
        }
    },
    PROV_LBI(Foo.PROV_LBI) {
        @Override
        public int provMethod(List<TXValue> txValueList, Context context) {
            return 408;
        }
    },
    UNKNOWN(Integer.MIN_VALUE) { // make sure this is not used in other IDs
                                 //decide if you actually need this
        @Override
        public int provMethod(List<TXValue> txValueList, Context context) {
            return -1;
        }            
    };

    private int id;

    private Prov(int id) {
        this.id = id;
    }

    public abstract int provMethod(List<TXValue> txValueList, Context context);

    public static Prov getById(int id) {
        for(Prov prov : Prov.values()) {
            if(id == prov.id) {
                return prov;
            }
        }
        //return null;
        //throw new IllegalArgumentException("Specified id was not found.");
        return Prov.UNKNOWN;
    }
}

Then you can do

public int procList(int prov, ArrayList<TXValue> txValueList, Context context)
{
    return Prov.getById(prov).provMethod(txValueList, context);
}
like image 143
EpicPandaForce Avatar answered Oct 16 '22 23:10

EpicPandaForce


To answer OP's question as it is framed -

Map<Integer, BiFunction<ArrayList<TXValue>,Context, Integer>> map = new HashMap<>();
{
    map.put(Foo.PROV_ONE, this::proc_one);
    // etc ....
    map.put(Foo.PROV_LBI, (x,y)->408 );
}

public int procList(int prov, ArrayList<TXValue> txValueList, Context context)
{
    if( ! map.contains(prov)) return -1;

    return map.get(prov).apply(txValueList, context);
}
like image 35
ZhongYu Avatar answered Oct 16 '22 22:10

ZhongYu