J'ai besoin de vérifier si au moins 1 élément dans une liste a x, y et z (tout en même temps). par exemple. L'article 1 a x, et l'élément 2 a y et z.
Je pensais qu'il serait préférable de le faire sans créer de multiples boucles et de vérifier l'un d'entre eux, mais de stocker une variable, puis de le vérifier pour que cela puisse 't être réglé sur false à nouveau une fois vrai. P>
On dirait que je manque probablement une meilleure façon de le faire, alors y a-t-il un? p>
Merci P>
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 Réponses :
Une carte de flux / réduisez la version de la boucle pour le plaisir. Pas sûr s'il vaut mieux être honnête. Mais au moins nous nous débarrassons de toutes les variables
Tellement d'allocations via arranges.aslist code> :(. Et arranges.Aslist (faux, faux, faux) code> est vraiment laid et inhabituel haha. Mais oui, une belle approche fonctionnelle
Oui, mais je ne sais pas si le flux l'optimise en interne. Nous devrions faire des tests pour cela. Sauf si quelqu'un sache.
Voici une approche extensible qui utilise une énumération pour que vous ne puissiez jamais toucher la logique de HasoneoFall code> à nouveau. Il vous suffit d'étendre l'énumé donné. 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);
}
}
Si vous allez coller à un JVM en dessous de 1,8, votre code est tout à fait bien!
Peut-être que vous pourriez sauver peu d'opérations comme briser la boucle une fois que vous avez trouvé un match pour les trois booléens et ne vérifiant que ceux qui sont non trouvé encore. p> Si vous n'êtes tout simplement bien d'utiliser des flux, il est préférable d'initialiser chacune des variables à sa création comme: P> 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.
J'aime votre dernier exemple de code pour sa simplicité: il est évident que ce qui se passe. Il s'arrête même tôt quand il l'a déjà jugé match. Bien fait
Je pense que l'OP demande à la mauvaise question ici et, par conséquent, la réponse ne conviendra pas à ses attentes ... peut-être qu'il devra améliorer les abstractions qu'il est mise en œuvre jusqu'à présent pour obtenir un code qui va bien ...
juste pour ajouter un bitset code> variante aussi, et sous l'hypothèse que la vérification a ... code> est une opération semi-coûteuse: 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;
}
Désolé, oui, il est censé être transmis.
Vous pouvez
BREAKE CODE> une fois que vous avez trouvé tous les 3, (et d'autres choses comme boutique dans un peu de place pour l'espace, Blah Blah). Mais je ne peux pas penser à une amélioration significative ici: /Oui, bonne idée. Merci :)
Pareil ici. Ceci est directement en avant, ne pas trop penser.
Il existe un site spécifique pour la revue de code, codereview.stackexchange.com
@Joakimdanielson dans son formulaire actuel La question serait fermée dans un rythme cardiaque sur l'examen du code
Vous pouvez utiliser
items.foreach (article -> {...}); code>, mais cela n'améliorerait rien, cela ne ferait que le faire dans un java-8-Way ...Vous pouvez simplement mettre la logique pour vérifier avec le
si code> à l'intérieur de la méthodenewavex code> et le définithasx code> en conséquence, au lieu d'avoir le logique dans la boucle.