EnumSet - Эффективный способ перемещения перекрестка

У меня есть два EnumSet.

Я хочу передать определенные значения от одного к другому, но сохранить в обоих объектах те значения, которые считаются «неподвижными». Пример кода...

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)

Я пробовал разные методы, но все они включают в себя множество шагов и создание временных EnumSet. Мне интересно, есть ли действительно эффективный метод и (конечно), что это такое.

Это делает мою голову в!

Спасибо.

ОБНОВЛЕНИЕ:

Один метод, который я пробовал (который, я думаю, может быть неэффективным) для достижения желаемого результата...

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)

person Bumpy    schedule 25.04.2014    source источник
comment
Прямо сейчас в вашем примере написано toTypes = METAL, WOOD, STRAW (i.e. METAL preserved, STRAW removed, WOOD & STICKS added), что не имеет смысла. Не могли бы вы исправить это? Не могли бы вы также уточнить, что именно вы пытаетесь сделать? Если возможно, покажите нам написанный вами код, который делает это, но вы не считаете его эффективным.   -  person Radiodef    schedule 25.04.2014
comment
Ах - исправлено, спасибо за это. (Говорил же вам, что у меня голова закружилась!) Я добавлю код, который пробовал, через мгновение (когда я отменю беспорядок, который я сделал из него! ;-)   -  person Bumpy    schedule 25.04.2014
comment
Спасибо, Radiodef. Я добавил некоторый код, который, кажется, дает желаемый результат, но кажется мне невероятно раздутым, тем более что я выполняю этот метод невероятно часто.   -  person Bumpy    schedule 25.04.2014


Ответы (1)


Если я правильно понимаю, способ сделать это без создания второй коллекции выглядит так:

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

fromSet.retainAll(MaterialTypes.IMMOVABLE_TYPES);

Или явно использовать итератор, чтобы вы могли пропустить один из вызовов 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();
    }
}

Это дает вам только две итерации по наборам и 2 созданных объекта, тогда как то, как вы это делаете в OP, использует более 5 из каждого. addAll/retainAll/removeAll будет использовать итератор внутри.

Но то, что вы делаете, не кажется ужасно неэффективным, и я бы лично не беспокоился об этом. На самом деле это довольно маленькие объекты. Если эта операция выполняется 10 000 раз в секунду и оказывается узким местом, более вероятно, что функцию необходимо перепроектировать, чтобы она не использовала коллекцию.

person Radiodef    schedule 25.04.2014
comment
Отлично, спасибо Radiodef за предоставление этих опций. - person Bumpy; 25.04.2014