【问题标题】:Checking for either/or with an EnumSet检查一个/或一个 EnumSet
【发布时间】:2013-02-11 01:59:03
【问题描述】:

所以我将应用程序中的一些位域转换为使用 EnumSet,我很好奇是否有更好的方法来比较 X|Y。目前我们正在做类似的事情:

if(bitfield & (X | Y) != 0) {
    //do stuff
}

等效的 EnumSet 似乎是:

if(enumSet.contains(X) || enumSet.contains(Y)) {
    //do stuff
}

有没有更清洁的方法来做到这一点?我知道你可以像这样检查containsAll()

EnumSet flagsToCheck = EnumSet.of(X, Y);
if(enumSet.containsAll(flagsToCheck)) {
    //do stuff
}

但这是针对您想知道是否设置了(X & Y) 的情况。是否有等效的方法来检查(X | Y)?我认为会有类似containsAny() 的方法,但我没有看到任何似乎有这种效果的东西。

【问题讨论】:

    标签: java enums bit-fields enumset


    【解决方案1】:

    我会说现有方法比您的按位方法更具可读性。它准确地表达了你的意思:如果集合包含 X,或者集合包含 Y……保持原样。已经很干净了。

    如果集合变大,你可以使用:

    EnumSet<Foo> valid = EnumSet.of(Foo.X, Foo.Y, Foo.A, Foo.B);
    valid.retainAll(enumSet);
    if (valid.isEmpty()) {
        ...
    }
    

    但我只会在较大的情况下保留它。对于两个或三个选项,我会使用速记形式。

    【讨论】:

    • 您可能想要相反的 (!valid.retainAll(enumSet)) 以避免更改原始设置。
    • 我正要评论@assylias 的观点。你可能是对的,它作为小型集合的个人更具可读性,只是看起来有点冗长。
    • @kcoppock:我更喜欢“冗长”而不是“聪明”,因为它实际上读起来更快。使用位掩码操作,我可能每次都必须仔细检查它——而使用简单的“X 或 Y”,代码读起来真的很自然。
    • @assylias 是对的。一种选择是根据您想要的枚举值创建一个新集合并相应地更改/验证。
    【解决方案2】:

    您可以使用AbstractSet 方法removeAll(如果找到任何元素则为真)。显然,您可能想使用原始集合的克隆来做到这一点。

    【讨论】:

    • 没错,这也是一个很好的检查方法。我只是想避免不必要的副本。
    • assylias 做相反的评论(从您正在寻找的值集中删除所有原始集)也适用于此。
    【解决方案3】:

    如果您无法更新集合,只需创建一个新集合...@assylias 是对的。一个选项是根据您想要的枚举值创建一个新集合并相应地更改/验证。

    public enum ResultingState {
        NOT_PERSISTED, PERSISTED, NOT_CALCULATED, CALCULATED;
    }
    EnumSet<ResultingState> errorsState = EnumSet.of(ResultingState.NOT_PERSISTED, ResultingState.NOT_CALCULATED);
    Collection<ResultingState> results = new HashSet<>(phaseResults.values());
    boolean containsAny = results.retainAll(errorsState) && results.size() > 0;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-05
      • 1970-01-01
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多