我需要检查列表中是否至少有一项具有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); }
}
答案 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)
一个有趣的循环图流/简化版本。不知道诚实是否更好。但是至少我们摆脱了所有变量
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*
实现以及其他因素。但它尽可能避免了大多数重新计算。