有没有编写此循环的更好方法?

时间:2019-07-05 11:35:14

标签: java loops

我需要检查列表中是否至少有一项具有X,Y和Z(不是同时全部)。例如项目1具有x,项目2具有y和z。

我认为最好这样做,而不创建多个循环并仅检查其中一个循环,而是存储一个变量,然后对其进行检查,这样就不能再次将其设置为false。

好像我可能缺少一种更好的方法来做到这一点,所以有吗?

谢谢

        boolean hasX = false;
        boolean hasY = false;
        boolean hasZ = false;

        for (ItemType item : Items) {
            if (!hasX) { hasX = DoesHaveX(item); }
            if (!hasY) { hasY = DoesHaveY(item); }
            if (!hasZ) { hasZ = DoesHaveZ(item); }
    }

4 个答案:

答案 0 :(得分:1)

如果您要坚持低于1.8的JVM,那么您的代码就可以了!

也许您可以跳过一些操作,例如一旦找到三个布尔值的匹配项就打破循环,并仅检查尚未找到的布尔值。

    for (ItemType item : items) {

        hasX = hasX || doesHaveX(item);
        hasY = hasY || doesHaveY(item);
        hasZ = hasZ || doesHaveZ(item);

        if (hasX && hasY && hasZ) {

            break;
        }
    }

如果您可以使用流,也许最好在创建时初始化每个变量,如下所示:

    boolean hasX = items.stream().anyMatch(this::doesHaveX); // goes trough the elements until a match is found.
    boolean hasY = items.stream().anyMatch(this::doesHaveY); // goes trough the elements until a match is found.
    boolean hasZ = items.stream().anyMatch(this::doesHaveZ); // goes trough the elements until a match is found.

答案 1 :(得分:0)

一个有趣的循环图流/简化版本。不知道诚实是否更好。但是至少我们摆脱了所有变量

  • 将每个项目映射到3个布尔值的列表(每个x,y,z属性一个)
  • 将整个列表简化为3个布尔值的列表(每个x,y,z属性一个),检查是否有任何项目具有每个值
  • 检查结果列表中的所有元素是否正确。
boolean allGood = items.stream()
    .map(i -> Arrays.asList(doesHaveX(i), doesHaveY(i), doesHaveZ(i)))
    .reduce(Arrays.asList(false, false, false),
            (acc, elem) -> Arrays.asList(acc.get(0) || elem.get(0), 
                                         acc.get(1) || elem.get(1), 
                                         acc.get(2) || elem.get(2)))
    .stream()
    .allMatch(Boolean::booleanValue);

答案 2 :(得分:0)

这是使用枚举的可扩展方法,因此您无需再触碰hasOneOfAll的逻辑。您只需要扩展给定的枚举即可。

import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

class StackOverflowQuestion56902308Scratch {
    class ItemType {
        boolean x;
        boolean y;
        boolean z;
    }

    enum ItemTypeCheck implements Predicate<ItemType> {
        HASX() {
            @Override
            public boolean test(ItemType itemType) {
                //TODO: implement me
                return itemType.x;
            }
        },
        HASY() {
            @Override
            public boolean test(ItemType itemType) {
                //TODO: implement me
                return itemType.y;
            }
        },
        HASZ() {
            @Override
            public boolean test(ItemType itemType) {
                //TODO: implement me
                return itemType.z;
            }
        }
    }

    public static boolean hasOneOfAll(List<ItemType> itemTypes) {
        Map<ItemTypeCheck, Boolean> result = new EnumMap<>(ItemTypeCheck.class);
        for (ItemType itemType : itemTypes) {
            for (ItemTypeCheck check : ItemTypeCheck.values()) {
                result.merge(check, check.test(itemType), Boolean::logicalOr);
            }
        }

        return result.values().stream().allMatch(hadOne -> hadOne);
    }

}

我个人不确定这是否设计过度,但是如果以后再添加其他检查,它可以减轻手动调整功能的麻烦。

答案 3 :(得分:0)

只需添加BitSet变体,并假设检查has...是半昂贵的操作即可:

private static final int xBit = 0;
private static final int yBit = 1;
private static final int zBit = 2;

public static boolean hasAll(final Collection<ItemType> items) {
    if (items.isEmpty()) return false;

    final BitSet bits = new BitSet(3);

    for (final ItemType item : items) {

        // Check if bit is already set to avoid
        // needless `has*` evaluation
        if (!bits.get(xBit) && hasX(item)) bits.set(xBit);

        if (!bits.get(yBit) && hasY(item)) bits.set(yBit);

        if (!bits.get(zBit) && hasZ(item)) bits.set(zBit);

        // You could repeat this INSIDE all of the 'if's
        // above to potentially avoid computing bits.get
        // but I'd sacrifice that for the slightly improved
        // readability.
        if (bits.cardinality() == 3) return true;
    }

    return false;
}

我不能告诉您这是更快还是什么,因为这取决于您的has*实现以及其他因素。但它尽可能避免了大多数重新计算。