Question

I have two EnumSets.

I want to transfer certain values from one to the other, but retain in both objects those values which are deemed "immoveable". Example code...

Public enum  MaterialTypes {

    STONE,
    METAL,
    WOOD,
    STICKS,
    STRAW;

    // STONE & METAL are "immoveable"...
    public static EnumSet<MaterialTypes> IMMOVEABLE_TYPES = EnumSet.of(STONE, METAL);

}

EnumSet<MaterialTypes> fromTypes = EnumSet.of(CellType.STONE, CellType.WOOD, CellType.STICKS);
EnumSet<MaterialTypes> toTypes   = EnumSet.of(CellType.METAL, CellType.STRAW);

// How to preserve the IMMOVEABLE types, but transfer all the other types from one object to the other?
// E.g. Desired result...

// fromTypes = STONE                (i.e. STONE preserved, WOOD & STICKS removed)
// toTypes   = METAL, WOOD, STICKS   (i.e. METAL preserved, STRAW removed, WOOD & STICKS added)

I've tried various methods, but all involve many steps and the creation of temporary EnumSets. I'm wondering if there is a really efficient method and (of course) what it is.

This is doing my head in!

Thanks.

UPDATE:

One method I tried (which I think may be ineffecient) to achieve desired result...

EnumSet<MaterialTypes> tmpSet = fromTypes.clone();   // Create temporary copy of fromTypes

tmpSet.removeAll(MaterialTypes.IMMOVEABLE_TYPES);    // Leave only the MOVEABLE types in tmpSet

fromTypes.retainAll(MaterialTypes.IMMOVEABLE_TYPES); // Leave only the IMMOVEABLE type in fromTypes

toTypes.retainAll(MaterialTypes.IMMOVEABLE_TYPES);   // Leave only the IMMOVEABLE types in toTypes

toTypes.addAll(tmpSet);                         // Add the MOVEABLE types (originally in fromTypes)
Was it helpful?

Solution

If I am understanding right, the way to do it without making a second collection is like this:

toSet.retainAll(MaterialTypes.IMMOVABLE_TYPES);
for(MaterialTypes mt : fromSet) {
    if(!MaterialTypes.IMMOVABLE_TYPES.contains(mt))
        toSet.add(mt);
}

fromSet.retainAll(MaterialTypes.IMMOVABLE_TYPES);

Or making explicit use of the Iterator so you can skip one of the calls to retainAll:

toSet.retainAll(MaterialTypes.IMMOVABLE_TYPES);
for(Iterator<MaterialTypes> it = fromSet.iterator(); it.hasNext();) {
    MaterialTypes mt = it.next();
    if(!MaterialTypes.IMMOVABLE_TYPES.contains(mt)) {
        toSet.add(mt);
        it.remove();
    }
}

Doing that nets you only two iterations across the Sets and 2 objects created whereas the way you're doing it in the OP uses more like 5 of each. addAll/retainAll/removeAll will use an Iterator internally.

But what you are doing doesn't seem terribly inefficient and I wouldn't personally worry about it. These are actually pretty small objects. If this operation is getting done 10,000 times a second and it's proved to be a bottleneck it's more likely the feature needs to be redesigned so it doesn't use a collection.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top