1
votes

Quelle est la meilleure façon de refactoriser plusieurs conditions dans une instruction if?

J'ai une instruction if avec beaucoup de conditions à l'intérieur, mais les conditions sont assez différentes. Cela a l'air vraiment volumineux. Je ne sais pas s'il existe un moyen de le faire.

// rqstCriteria is a List
// anotherCriteria is a List
// key# are the different values that I want to see if it has
if (
rqstCriteria.contains(key1) || 
rqstCriteria.contains(key2) || 
rqstCriteria.contains(key3) || 
rqstCriteria.contains(key4) || 
rqstCriteria.contains(key5) && 
(anotherCriteria != null && 
  (anotherCriteria.contains(key1) || 
   anotherCriteria.contains(key2) || 
   anotherCriteria.contains(key3) || 
   anotherCriteria.contains(key4) || 
   anotherCriteria.contains(key5))
{...} 


3 commentaires

Copie possible de Meilleur moyen de formater plusieurs Les conditions 'ou' dans une instruction if (Java) utilisent ceci pour chacune de vos listes, puis créent un arbre if plus petit


if (rqstCriteria.stream (). anyMatch (keySet :: contains) etc, où keySet = Set.of (key1, key2, ...) .


L'exemple semble étrange d'avoir rqstCriteria.contains (key5) && pas (rqstCriteria.contains (key1) ... rqstCriteria.contains (key5)) && . Est-ce une faute de frappe ou une partie de la question - d'avoir ces vérifications exactement comme ça?


5 Réponses :


1
votes

Commencez par rassembler toutes les clés dans la liste et en utilisant java-8 streams.anyMatch

if(list.stream().anyMatch(i->rqstCriteria.contains(i)) && 
        Objects.nonNull(anotherCriteria) && 
        list.stream().anyMatch(j->anotherCriteria.contains(j))) {

}

Et je dirais de déplacer le null code> vérifiez à l'extérieur de si bloquer, le meilleur moyen est de renvoyer une liste vide ou vous pouvez utiliser l'approche ci-dessous

List<String> list = List.of("key1","key2");  //or Arrays.asList()

if(list.stream().anyMatch(i->rqstCriteria.contains(i)) && list.stream().anyMatch(j->anotherCriteria.contains(j))) {

}


0 commentaires

0
votes

Vous pouvez écrire une méthode d'aide containsAny (merci à @chrylis pour l'optimiser):

if (containsAny(rqstCriteria, key1, key2, key3, key4, key5) 
    && containsAny(anotherCriteria, key1, key2, key3, key4, key5)) {
    ...
} 

Et ensuite l'utiliser dans vos instructions if: p >

public <T> boolean containsAny(Collection<T> c, T... keys) {
    return c != null && Arrays.stream(keys).anyMatch(c::contains);
}  


2 commentaires

Arrays.stream (clés) serait beaucoup moins cher que de copier dans un HashSet .


@chrylis je suis tout à fait d'accord, merci



0
votes

'' 'réponse courte et inutile' '' ': repensez votre modèle pour ne pas avoir besoin de plusieurs instructions if.

'' 'pas-si-long-mais-insightfull-and-pragmmatic-answer' ': Créez une hiérarchie de classes où chacune décrit une entité dont les propriétés seraient testées sur chaque cas If pertinent.

La classe Stuffy serait des objets qui remplissent, par définition, les conditions pour correspondre à if-1. Thingy serait la même chose à propos de if-2 ... Tous implémenteraient Anything ...

Ensuite, au lieu de votre grosse méthode doIt () avec un sale-laid if, chaque classe concrète implémenterait son propre doIt () (avec le code que vous mettriez sur chaque clause ifX).


0 commentaires

0
votes

Je pense que votre état est étrange. Mais

if (Stream.of(key1, key2, key3, key4).anyMatch(rqstCriteria::contains) ||
    rqstCriteria.contains(key5) && 
    anotherCriteria != null && 
    Stream.of(key1, key2, key3, key4, key5).anyMatch(anotherCriteria::contains))
{} 


0 commentaires

0
votes

Pour ajouter une autre approche utilisant des prédicats:

En supposant que vos listes de critères stockent des chaînes, créez un ensemble contenant vos clés:

if(containsOneOfMyKeys.test(rqstCriteria) &&
   isNotNullOrEmpty.and(containsOneOfMyKeys).test(anotherCriteria)){
   //do something
}

et deux prédicats qui acceptent une liste

Predicate<List<String>> containsOneOfMyKeys = l -> l.stream().anyMatch(s -> myKeys.contains(s));
Predicate<List<String>> isNotNullOrEmpty = l -> Objects.nonNull(l) && !l.isEmpty();

Ensuite, vous pouvez simplifier votre instruction if d'une manière lisible comme:

Set<String> myKeys = Set.of("key1","key2","key3","key4","key5");


0 commentaires