0

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)
Bumpy
  • 1,290
  • 1
  • 22
  • 32
  • Right now your example says `toTypes = METAL, WOOD, STRAW (i.e. METAL preserved, STRAW removed, WOOD & STICKS added)` which doesn't make sense. Can you please correct it? Can you also please clarify what you are trying to do exactly? If possible, show us the code you've written that does this but you don't think is efficient. – Radiodef Apr 25 '14 at 02:30
  • Ah - corrected, thanks for that. (Told you this was doing my head in!) I'll add the code I tried in a moment (when I've undone the mess I've made of it! ;-) – Bumpy Apr 25 '14 at 02:32
  • Thanks Radiodef - I've added some code that seems to achieve the desired result, but seems incredibly overblown to me, especially since I'm executing this method incredibly frequently. – Bumpy Apr 25 '14 at 02:52

1 Answers1

2

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.

Radiodef
  • 37,180
  • 14
  • 90
  • 125