37

私は持っている;

public enum Detailed {
    PASSED, INPROCESS, ERROR1, ERROR2, ERROR3;
}

次のように変換する必要があります。

public enum Simple {
    DONE, RUNNING, ERROR;
}

したがって、最初はPASSED->DONEINPROCESS->RUNNINGですが、すべてのエラーは次のようになりますERROR。明らかに、すべての値のケースを作成することは可能ですが、より良い解決策があるかもしれません?

4

7 に答える 7

35

個人的には、を作成Map<Detailed, Simple>して明示的に実行します。あるいは、switchステートメントを使用する可能性もあります。

もう1つの方法は、マッピングをコンストラクターに渡すことです。もちろん、一方向にしか実行できません。

public enum Detailed {
    PASSED(Simple.DONE),
    INPROCESS(Simple.RUNNING),
    ERROR1(Simple.ERROR),
    ERROR2(Simple.ERROR),
    ERROR3(Simple.ERROR);

    private final Simple simple;

    private Detailed(Simple simple) {
        this.simple = simple;
    }

    public Simple toSimple() {
        return simple;
    }
}

(これは、ポリモーフィズムを使用するTedのアプローチよりも単純です。これは、実際には異なる動作を提供しようとしているのではなく、異なる単純なマッピングだけであるためです。)

序数の値で何か狡猾なことをする可能性はありますが、それはそれほど明白ではなく、より多くのコードを必要とします-私は何の利益もないと思います。

于 2012-06-18T05:49:47.093 に答える
31

1 つの方法はasSimple()Detailed列挙型でメソッドを定義することです。

public enum Detailed {
    PASSED {
        @Override
        Simple asSimple() {
            return DONE;
        }
    },
    INPROCESS {
        @Override
        Simple asSimple() {
            return RUNNING;
        }
    },
    ERROR1,
    ERROR2,
    ERROR3;
    public Simple asSimple() {
        return Simple.ERROR; // default mapping
    }
}

マッピングを行いたい場合は、メソッドを呼び出すだけです。

Detailed code = . . .
Simple simpleCode = code.asSimple();

マッピングの知識をDetailed列挙型 (おそらくそれが属している場所) に入れるという利点があります。Simpleのコードに の知識が混在しているという欠点がありますDetailed。システムのアーキテクチャによっては、これは悪いことかもしれませんし、そうでないかもしれません。

于 2012-06-18T05:48:12.630 に答える
10

EnumMapを使用する

変換サービスを実装することで、外部 xml インターフェイスを内部ドメイン モデルから分離します。これには、jaxb によって生成されたコードからドメイン モデルの列挙型への列挙型のマッピングが含まれます。

静的 EnumMap を使用すると、変換を担当するクラス内に変換の問題がカプセル化されます。そのまとまり。

@Service
public class XmlTransformer {

    private static final Map<demo.xml.Sense, Constraint.Sense> xmlSenseToSense;
    static {
        xmlSenseToSense = new EnumMap<demo.xml.Sense, Constraint.Sense> (
            demo.xml.Sense.class);
        xmlSenseToSense.put(demo.xml.planningInterval.Sense.EQUALS, 
            Constraint.Sense.EQUALS);
        xmlSenseToSense.put(demo.xml.planningInterval.Sense.GREATER_THAN_OR_EQUALS, 
            Constraint.Sense.GREATER_THAN_OR_EQUALS);
        xmlSenseToSense.put(demo.xml.planningInterval.Sense.LESS_THAN_OR_EQUALS, 
            Constraint.Sense.LESS_THAN_OR_EQUALS);
    }
    ...
}
于 2014-12-05T08:22:02.353 に答える
1

テッドの答えは非常にJavalyですが、表現

passed == PASSED ? DONE : ERROR

仕事もします。

于 2012-06-18T05:52:39.187 に答える
0

テスト付きの単純な列挙型マッパーは次のとおりです。

- 実装

-- 列挙型

public enum FirstEnum {

A(0), B(1);

private final int value;

private FirstEnum(int value) {
    this.value = value;
}

public int getValue() {
    return value;
}
}

public enum  SecondEnum {

C(0), D(1);

private final int valueId;

private SecondEnum(int valueId) {
    this.valueId = valueId;
}

public int getValueId() {
    return valueId;
}

}

--マッパー

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.Validate;

import com.google.common.collect.Sets;

public class EnumPropertyMapping {

private final Map<?, ?> firstMap;
private final Map<?, ?> secondMap;

private final Class<?> firstType;
private final Class<?> secondType;

private EnumPropertyMapping(
        Map<?, ?> firstMap, Map<?, ?> secondMap, Class<?> firstType, Class<?> secondType) {

    this.firstMap = firstMap;
    this.secondMap = secondMap;
    this.firstType = firstType;
    this.secondType = secondType;
}

public static Builder builder() {
    return new Builder();
}

@SuppressWarnings("unchecked")
public <R> R getCorrespondingEnum(Object mappedEnum) {
    Validate.notNull(mappedEnum, "Enum must not be NULL");
    Validate.isInstanceOf(Enum.class, mappedEnum, "Parameter must be an Enum");

    if (firstType.equals(mappedEnum.getClass())) {
        return (R) firstMap.get(mappedEnum);
    }

    if (secondType.equals(mappedEnum.getClass())) {
        return (R) secondMap.get(mappedEnum);
    }

    throw new IllegalArgumentException("Didn't found mapping for enum value: " + mappedEnum);
}

public static class Builder {

    private final Map<Object, Object> firstEnumMap = new HashMap<>();
    private final Map<Object, Object> secondEnumMap = new HashMap<>();
    private Class<?> firstEnumType;
    private Class<?> secondEnumType;

    public <T extends Enum<T>> Builder addFirst(Class<T> enumType, String propertyName) {
        firstEnumType = enumType;
        initMap(firstEnumMap, enumType.getEnumConstants(), propertyName);
        return this;
    }

    public <T extends Enum<T>> Builder addSecond(Class<T> enumType, String propertyName) {
        secondEnumType = enumType;
        initMap(secondEnumMap, enumType.getEnumConstants(), propertyName);
        return this;
    }

    private void initMap(Map<Object, Object> enumMap, Object[] enumConstants, String propertyName) {
        try {
            for (Object constant : enumConstants) {
                enumMap.put(PropertyUtils.getProperty(constant, propertyName), constant);
            }
        } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException ex) {
            throw new IllegalStateException(ex);
        }
    }

    public EnumPropertyMapping mapEnums() {
        Validate.isTrue(firstEnumMap.size() == secondEnumMap.size());
        Validate.isTrue(Sets.difference(firstEnumMap.keySet(), secondEnumMap.keySet()).isEmpty());

        Map<Object, Object> mapA = new HashMap<>();
        Map<Object, Object> mapB = new HashMap<>();

        for (Map.Entry<Object, Object> obj : firstEnumMap.entrySet()) {
            Object secondMapVal = secondEnumMap.get(obj.getKey());
            mapA.put(obj.getValue(), secondMapVal);
            mapB.put(secondMapVal, obj.getValue());
        }
        return new EnumPropertyMapping(mapA, mapB, firstEnumType, secondEnumType);
    }
}

}

- テスト

import org.junit.Test;

import com.bondarenko.common.utils.lang.enums.FirstEnum;
import com.bondarenko.common.utils.lang.enums.SecondEnum;

import static junit.framework.TestCase.assertEquals;

public class EnumPropertyMappingTest {

@Test
public void testGetMappedEnum() {
    EnumPropertyMapping mapping = EnumPropertyMapping.builder()
                                                                                                     .addSecond(SecondEnum.class, "valueId")
                                                                                                     .addFirst(FirstEnum.class, "value")
                                                                                                     .mapEnums();

    assertEquals(SecondEnum.D, mapping.getCorrespondingEnum(FirstEnum.B));
    assertEquals(FirstEnum.A, mapping.getCorrespondingEnum(SecondEnum.C));
}

}
于 2015-01-15T21:30:46.923 に答える
0

私には、それはプログラミングの問題というよりも概念的な問題のように思えます。「Simple」列挙型を削除して、プログラムのすべての場所で代わりに別の列挙型を使用してみませんか?

別の例でそれをより明確にするために: 週の稼働日 (月曜日から金曜日) の列挙型と、すべての曜日 (月曜日から日曜日) の別の列挙型を本当に定義しようとしますか?

于 2012-06-18T05:54:29.773 に答える