# One-line initialisation for a constant list with all entries except one from another list

I'm looking to simplify the initialisation of the second constant, preferably to just one line. Any ideas? Anything from Guava or JDK (up to 1.6) is ok to use.

enum Box {
FREEMIUM,
EXTRA_STORIES,
TOP_STORIES,
TOP_CHARACTERS,
TOP_THEMES,
TOP_ARTISTS,
TOP_ISSUES
// several more ...
}

final static List<Box> FREEMIUM_BOXES = ImmutableList.copyOf(Box.values());
final static List<Box> DEFAULT_BOXES = initDefaultBoxes(); // All except FREEMIUM

static List<Box> initDefaultBoxes() {
List<Box> boxes = Lists.newArrayList(FREEMIUM_BOXES);
boxes.remove(Box.FREEMIUM);
return ImmutableList.copyOf(boxes);
}


Granted, it's not that bad, but still I'd like to get rid of the init method. :-) (Static initialiser wouldn't be any better.)

NB: I want to define the order of boxes only once, in the enum definition itself, so ImmutableList.of(PROMO_HEADER, EXTRA_STORIES, ...) is not considered a good solution for the purposes of this refactoring.

A single-statement Guava solution would be this, using filter() and a Predicate, but arguably this is less clean than the original, because this kind of stuff is verbose in Java...

final static List<Box> DEFAULT_BOXES =
ImmutableList.copyOf(Iterables.filter(FREEMIUM_BOXES, new Predicate<Box>() {
@Override
public boolean apply(Box box) {
return box != Box.FREEMIUM;
}
}));


## Resolution

Went with this, which is the cleanest option considering I indeed need the constants defined as Lists:

final static List<Box> FREEMIUM_BOXES = ImmutableList.copyOf(Box.values());
final static List<Box> DEFAULT_BOXES =
Sets.immutableEnumSet(EnumSet.complementOf(EnumSet.of(Box.FREEMIUM))).asList();


Use EnumSet for that. From docs:

A specialized Set implementation for use with enum types. (...) The iterator returned by the iterator method traverses the elements in their natural order (the order in which the enum constants are declared).

It's also very efficent:

Implementation note: All basic operations execute in constant time. They are likely (though not guaranteed) to be much faster than their HashSet counterparts. Even bulk operations execute in constant time if their argument is also an enum set.

final static Set<Box> DEFAULT_BOXES =
EnumSet.complementOf(EnumSet.of(Box.FREEMIUM));


or if you prefer immutable one, use Sets.immutableEnumSet(Iterable):

final static ImmutableSet<Box> DEFAULT_BOXES =
Sets.immutableEnumSet(EnumSet.complementOf(EnumSet.of(Box.FREEMIUM)));


or if you insist for List (but why would you?):

final static ImmutableList<Box> DEFAULT_BOXES =
Sets.immutableEnumSet(EnumSet.complementOf(EnumSet.of(Box.FREEMIUM))).asList();


P.S. All constants can be represented as:

final static Set<Box> FREEMIUM_BOXES = EnumSet.allOf(Box.class); // or wrap it with Sets.immutableEnumSet to make it ImmutableSet

• Why List? Simple: order matters. This affects the order of UI elements and that must be correct. It might work with some Sets too, but when the constant is defined as List, it's explicit and guaranteed that the order will be right. – Jonik Jan 22 '14 at 15:44
• ImmutableSet also has defined order (insertion order), so does Sets.immutableEnumSet (The iteration order of the returned set follows the enum's iteration order, so this is what you want), you can always use .asList() on it which is a view (does not copy elements). Anyway, I agree with you, and that said I'd use .asList() with ImmutableList. – Xaerxess Jan 22 '14 at 15:46
• Yes, I might actually define it as ImmutableSet, since it has "reliable, user-specified iteration order". Good call on EnumSet.complementOf() and EnumSet.allOf(), thanks! – Jonik Jan 22 '14 at 15:52
• Ah, actually I will stick with List as the type, because what I need from these constants is get(int index) (in a method called createView(int position)). Using Set would unnecessarily complicate that code. – Jonik Jan 22 '14 at 15:59