java—提取所有真属性并添加到列表中

knsnq2tg  于 2021-07-07  发布在  Java
关注(0)|答案(4)|浏览(327)

我有一个java类,它有3个类似这样的布尔属性

boolean isActive;
boolean isEnable;
boolean isNew;

每个属性都与一个枚举相关(例如,active、enable、new)。我想要两个枚举列表。一个只有与真属性值相关的枚举,一个用于假属性值。
我只是想说清楚。使用if else语句

Set<FlagEnum> flagSet = new HashSet<>();
Set<FlagEnum> falseFlagSet = new HashSet<>();

if (object.isActive()) {
    flagSet.add(ACTIVE);
} else {
    falseFlagSet.add(ACTIVE);
}
if (object.isEnable()) {
    flagSet.add(ENABLE);
} else {
    falseFlagSet.add(ENABLE);
}
if (object.isNew()) {
    flagSet.add(NEW);
} else {
    falseFlagSet.add(NEW);
}

有没有办法避免所有这些呢?
我试过这样的东西

Map<boolean, List<Pair<boolean, FlagEnum>>> res = Stream.of(
new Pair<>(object.isActive(), ACTIVE),
new Pair<>(object.isNew(), NEW),
new Pair<>(object.isEnable(), ENABLE))
.collect(Collectors.partitioningBy(Pair::getKey));

但由此产生的结构是一个额外的复杂性,我想避免。
在我的实际例子中,我有超过15个布尔属性。。。

rjjhvcjd

rjjhvcjd1#

您可以使用反射来获取所有方法,然后检查 getReturnType() == boolean.class . 问题是方法名和枚举之间的连接。如果每一个都像没有'is'的方法那样命名,那么您可以使用 FlagEnum.valueOf() 从方法名称检索枚举值并使用它。

9wbgstp7

9wbgstp72#

我认为这可能是最简单和最清楚的方式来做我需要的

Map<Boolean, Set<FlagEnum>> flagMap = new HashMap<>();
        flagMap.computeIfAbsent(object.isActive(), h -> new HashSet()).add(ACTIVE);
        flagMap.computeIfAbsent(object.isEnabled(), h -> new HashSet()).add(ENABLE);
        flagMap.computeIfAbsent(object.isNew(), h -> new HashSet()).add(NEW);

//to get TRUE set simply :
flagMap.get(true);

你怎么认为?

ldfqzlk8

ldfqzlk83#

您可以为此使用私有助手方法。

private void addFlagSet(boolean condition, FlagEnum flagEnum,
                       Set<FlagEnum> flagSet, Set<FlagEnum> falseFlagSet) {

    Set<FlagEnum> chosenFlagSet = condition ? flagSet: falseFlagSet;
    chosenFlagSet.add(flagEnum);
}

称之为:

addFlagSet(object.isActive(), FlagEnum.ACIVE, flagSet, falseFlagSet);
addFlagSet(object.isNew(), FlagEnum.NEW, flagSet, falseFlagSet);
addFlagSet(object.isEnable(), FlagEnum.ENABLE, flagSet, falseFlagSet);
s3fp2yjn

s3fp2yjn4#

你可以用不同的方法来简化它。哪一个是合理的,取决于你的确切要求。
你可以推导出 falseFlagSet 微不足道的 flagSet 使用 EnumSet.complementOf 在填充 flagSet :

EnumSet<FlagEnum> falseFlagSet = EnumSet.complementOf(flagSet);

这假设所有 FlagEnum 值具有相应的标志。如果不是这样,那么你需要构造一个 EnumSet 所有具有标志和减法的枚举 flagSet 从那以后 removeAll .

1已经不再需要 else 在级联中,将代码简化为

if (object.isActive()) {
    flagSet.add(ACTIVE);
}
if (object.isEnable()) {
    flagSet.add(ENABLE);
}
if (object.isNew()) {
    flagSet.add(NEW);
}

如果有足够多的不同标志,则可以创建从getter方法到 FlagEnum 价值观如下:

Map<Function<YourClass,Boolean>,FlagEnum> GETTERS = Map.of(
    YourClass::isActive, FlagEnum.ACTIVE,
    YourClass::isNew, FlagEnum.NEW,
    YourClass::isEnable, FlagEnum.ENABLE);

然后,您可以使用它使整个流程成为数据驱动的:

EnumSet<FlagEnum> getFlagSet(YourClass yourObject) {
  EnumSet<FlagEnum> result = EnumSet.noneOf(FlagEnum.class);
  for (Map.Entry<Function<YourClass,Boolean>, FlagEnum> getter : GETTERS.entrySet()) {
    if (getter.getKey().apply(yourObject)) {
      result.add(getter.getValue());
    }
  }
  return result;
}

如果标志的数量非常大,那么您可以完全切换到反射,并使用字符串比较动态地检测标志和匹配的getter,但我不建议使用这种方法。如果您需要这样的功能,那么您可能应该切换到支持这种功能的框架,而不是自己实现它。
最后两个显然只有在旗子数量很大的时候才有意义。如果它实际上只有3个标志,那么我不介意,只要有3个简单的 if 声明。
作为轻微切线: GETTERS 上面肯定是一个不可变的Map(用 Collections.unmodifiableMap 或者用Guava之类的 ImmutableMap )可以说,这同样适用于 getFlagSet 方法。为了简洁起见,我把这些删掉了。

相关问题