Here are two options:

Option 1:

enum QuizCategory {

    CATEGORY_1(new MyCollection<Question>()
                    .add(Question.QUESTION_A)
                    .add(Question.QUESTION_B)
                    .add...),

    CATEGORY_2(new MyCollection<Question>()
                    .add(Question.QUESTION_B)
                    .add(Question.QUESTION_C)
                    .add...), 

    ...

    ;

    public MyCollection<Question> collection;

    private QuizCategory(MyCollection<Question> collection) {
        this.collection = collection;
    }

    public Question getRandom() {
        return collection.getRandomQuestion();
    }

}


Option 2:

enum QuizCategory2 {

    CATEGORY_1 {

        @Override
        protected MyCollection<Question> populateWithQuestions() {
            return new MyCollection<Question>()
                                .add(Question.QUESTION_A)
                                .add(Question.QUESTION_B)
                                .add...;
        }
    },

    CATEGORY_2 {

        @Override
        protected MyCollection<Question> populateWithQuestions() {
            return new MyCollection<Question>()
                                .add(Question.QUESTION_B)
                                .add(Question.QUESTION_C)
                                .add...;
        }
    };

    public Question getRandom() {
        MyCollection<Question> collection = populateWithQuestions();
        return collection.getRandomQuestion();
    }

    protected abstract MyCollection<Question> populateWithQuestions();

}


There will be around 1000 categories, each containing 10 - 300 questions (100 on average). At runtime typically only 10 categories and 30 questions will be used. Each question is itself an enum constant (with its fields and methods).

I'm trying to decide between those two options in the mobile application context. I haven't done any measurements since I have yet to write the questions and would like to gather more information before committing to one or another option. As far as I understand:

(a) Option 1 will perform better since there will be no need to populate the collection and then garbage-collect the questions;
(b) Option 1 will require extra memory: 1000 categories x 100 questions x 4 bytes for each reference = 400 Kb, which is not significant.

So I'm leaning to Option 1, but just wondered if I'm correct in my assumptions and not missing something important? Perhaps someone has faced a similar dilemma? Or perhaps it doesn't actually matter that much?

The return value of main is to be passed to the operating system (any operating system) in a single, consistent way.  The information that the operating system needs to know is "did the program terminate successfully, or was there an error?"

If this is a string, the response becomes difficult in different languages.  The internals of a Pascal string (first byte is length) and a FORTRAN string (fixed, padded to some value) and a C string (null terminated) are all different.  This would make returning a consistent value to the operating system challenging.  Assuming that this was solved, what would you do to answer the question the OS had of the program?  String comparisons are fraught with errors ("success" vs "Success"), and while the error may be more useful to a human, it is more difficult for the operating system or another program (shell) to deal with.  There also were significant differences even in the strings themselves -- EBCDIC (with all of its code pages) vs. ASCII.

Floats and doubles provide no additional value over the integer for communicating back data to the OS (and shell).  For the most part, neither of these parts of the computer deal with floating point numbers.  Doubles are also not enumerable making comparisons difficult.  Not being enumerable, they make reporting what the error was (assuming you have picked a particular value for success).  Again, floating points are not consistent - a float on an 8 bit machine was different than the float on a 16 bit and a 32 bit machine (and those are just the 'normal' ones - even within IBM, floating point wasn't standardized between machines by the same manufacturer until the 1980's).  And then you've got decimal vs. binary computers.  Floating point values aren't consistent and don't provide meaningful data back.

That really leaves us with the byte and integer as options.  The convention that was established was '0' was success, and anything else was an error.  An integer gives more room than a byte for reporting the error.  It can be enumerated (return of 1 means XYZ, return of 2 means ABC, return of 3, means DEF, etc..) or used as flags (0x0001 means this failed, 0x0002 means that failed, 0x0003 means both this and that failed).  Limiting this to just a byte could easily run out of flags (only 8), so the decision was probably to use an integer.
