web-dev-qa-db-fra.com

ArrayList contient la sensibilité à la casse

J'utilise actuellement la méthode includes de la classe ArrayList pour effectuer une recherche. Existe-t-il un moyen de rendre cette recherche insensible à la casse en Java? J'ai trouvé qu'en C #, il est possible d'utiliser OrdinalIgnoreCase. Existe-t-il un équivalent Java ou un autre moyen de le faire? Merci.

59
John

Vous pouvez l'utiliser exactement comme n'importe quel autre ArrayList. Vous pouvez transmettre cette liste à un autre code et le code externe n'aura pas à comprendre les classes wrapper de chaînes.

public class CustomStringList3 extends ArrayList<String> {
    @Override
    public boolean contains(Object o) {
        String paramStr = (String)o;
        for (String s : this) {
            if (paramStr.equalsIgnoreCase(s)) return true;
        }
        return false;
    }
}
64
Aaron J Lang

Si vous utilisez Java 8, essayez:

List<String> list = ...;
String searchStr = ...;
boolean containsSearchStr = list.stream().filter(s -> s.equalsIgnoreCase(searchStr)).findFirst().isPresent();
33
Josh M

En Java8, en utilisant anyMatch

List<String> list = Arrays.asList("XYZ", "ABC");
String matchingText = "xYz";

boolean isMatched = list.stream().anyMatch(matchingText::equalsIgnoreCase);
26
Free-Minded

Traditionnellement, vous pouvez développer votre propre logique pour comparer les chaînes contenues par un ArrayList . Il existe peut-être plusieurs façons de procéder, comme celle présentée ci-dessous.

public boolean containsCaseInsensitive(String strToCompare, ArrayList<String>list)
{
    for(String str:list)
    {
        if(str.equalsIgnoreCase(strToCompare))
        {
            return(true);
        }
    }
    return(false);
}

Pourquoi ne devrait-on pas utiliser des moyens directs et pratiques comme un SortedSet comme indiqué ci-dessous avec un comparateur insensible à la casse ?.

Set<String> a = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);

a.add("A");
a.add("B");
a.add("C");


Set<String> b = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);

b.add("a");
b.add("b");
b.add("c");

System.out.println(b.equals(a));

Souhaitez comparer deux ensembles différents en ignorant le cas et renvoyer true, dans cette situation particulière et votre comparaison se déroulerait sans problème.

14
Lion

En regardant le API Java , il n’existe pas de telle méthode pour contient.

Mais vous pouvez faire au moins deux choses:

  1. Remplacez la méthode equals dans votre objet ArrayList par la vôtre, ou equalsIgnoreCase (str)
  2. Ecrivez votre propre méthode includes, qui doit parcourir les entités ArrayList et effectuer une vérification manuelle.

    ArrayList<String> list = new ArrayList<String>();
    ...
    containsIgnoreCase("a", list);
    
    public boolean containsIgnoreCase(String str, ArrayList<String> list){
        for(String i : list){
            if(i.equalsIgnoreCase(str))
                return true;
        }
        return false;
    }
    
9
HeavenAgain

En supposant que vous avez un ArrayList<String>

La seule façon pour moi de faire cela serait de créer une classe wrapper très légère autour d'une chaîne et de remplacer equals et hashcode pour ignorer la casse, en utilisant equalsIgnoreCase() si possible. Ensuite, vous auriez un ArrayList<YourString>. C'est un peu laide idée cependant.

7
rfeak

Vous pouvez utiliser IterableUtils et Predicate de collections4 (Apache).

List<String> pformats= Arrays.asList("Test","tEst2","tEsT3","TST4");

Predicate<String> predicate  = (s) -> StringUtils.equalsIgnoreCase(s, "TEST");
if(IterableUtils.matchesAny(pformats, predicate)) {
    // do stuff
}

IterableUtils (collections4): org.Apache.commons.collections4.IterableUtils.html

3
bpedroso

Pour Java8

list.stream (). anyMatch (s -> s.equalsIgnoreCase (yourString))

Pour <Java8

  • comme suggéré par Aaron J Lang ci-dessus
  • Ou si vous connaissez le cas de votre liste (tout en haut/tout en bas), convertissez la chaîne de recherche en casse appropriée avant de
2
Om.

La méthode contains est basée sur ce que la méthode equals des objets stockés dans votre ArrayList est renvoyée. Donc oui, cela est possible si vous utilisez des objets où equals utilise une comparaison insensible à la casse.

Ainsi, vous pouvez par exemple utiliser une classe comme celle-ci (le code peut encore contenir des fautes de frappe)

public class CaseInsensitiveString{
  private final String contents;

  public CaseInsensitiveString( String contents){ this.contents = contents; }

  public boolean equals( Object o ){
    return o != null && o.getClass() == getClass() && o.contents.equalsIgnoreCase( contents);
  }

  public int hashCode(){
    return o.toUpperCase().hashCode();
  }
}
2
Robin

Une autre solution:

public class IgnorecaseList extends ArrayList<String>{

    @Override
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    } 

    @Override
    public int indexOf(Object o) {
        if(o instanceof String){
            for (int i = 0; i < this.size(); i++) {
                if(((String)o).equalsIgnoreCase(get(i))){
                    return i;
                }
            }
        }
        return -1;
    }
}

La méthode contains() utilise indexOf ... Dans cette solution, vous pouvez également savoir où position correspond à la chaîne. list.add("a") -> list.indexOf("A") == 0 ou list.indexOf("a") == 0 ..

Vous devriez également envisager d'utiliser un ensemble au lieu de la liste.

2
Rogel Garcia

La méthode includes () de ArrayList vérifie l'égalité en appelant la méthode equals () sur l'objet fourni (PAS les objets du tableau). Par conséquent, une méthode légèrement astucieuse consiste à créer une classe wrapper autour de l'objet String, comme ceci:

class InsensitiveStringComparable {
    private final String val;

    public InsensitiveStringComparable(String val) {
        this.val = val;
    }

    @Override
    public boolean equals(Object x) {
        if (x == this)
            return true;
        else if (x == null)
            return false;
        else if (x instanceof InsensitiveStringComparable)
            return ((InsensitiveStringComparable) x).val.equalsIgnoreCase(val);
        else if (x instanceof String)
            /* Asymmetric equals condition */
            return val.equalsIgnoreCase((String) x);
        else
            return false;
    }

    @Override
    public int hashCode() {
        return val.toUpperCase().hashCode();
    }
}

Ensuite, vous pouvez l'utiliser pour effectuer votre test. Exemple de test "manuel":

public class Test {
    public static void main(String[] args) {
        ArrayList<Object> a = new ArrayList<Object>();
        a.add("test");
        System.out.println(a.contains(new InsensitiveStringComparable("TEST")));
        System.out.println(a.contains(new InsensitiveStringComparable("tEsT")));
        System.out.println(a.contains(new InsensitiveStringComparable("different")));
    }
}
2
Seramme

Dans mon cas, comme toutes mes chaînes dans ArrayList sont dans le cas, j'exécute simplement la méthode String. toLowerCase () sur le paramètre contains (). Comme ça:

If (yourArrayList.contains (parameterInput.toLowerCase()) {
    // your code here
}

Comme vous pouvez le voir, vous pouvez faire l’opposé, si yout arrayList a des chaînes upperCase:

If (yourArrayList.contains (parameterInput.toUpperCase ()) {
    // your code here
}

En utilisant cette approche, vous n'avez pas besoin de remplacer quoi que ce soit. L'exception est dans le cas où votre tableauListe a un mélange de majuscules et de minuscules.

2
mizerablebr

La fonction supplémentaire n’est pas nécessaire, les résultats souhaités peuvent être obtenus en convertissant les chaînes comparées en majuscules ou minuscules.

(Je sais que cela a été suggéré dans les commentaires, mais pas complètement fourni comme réponse)

Ex: ignore la casse lors du filtrage du contenu d'une liste JList en fonction de l'entrée fournie par un JTextField:

private ArrayList<String> getFilteredUsers(String filter, ArrayList<User> users) {
    ArrayList<String> filterUsers = new ArrayList<>();
    users.stream().filter((user) -> (user.getUsername().toUpperCase().contains(filter.toUpperCase()))).forEach((user)-> {
        filterUsers.add(user.getUsername());
    });
    this.userList.setListData(filterUsers.toArray());
    return filterUsers;
    /** 
     *  I see the redundancy in returning the object... so even though,
     *  it is passed by reference you could return type void; but because
     *  it's being passed by reference, it's a relatively inexpensive
     *  operation, so providing convenient access with redundancy is just a 
     *  courtesy, much like putting the seat back down. Then, the next
     *  developer with the unlucky assignment of using your code doesn't 
     *  get the proverbially dreaded "wet" seat.
     */
}
1
JReyn

Si vous ne voulez pas créer une nouvelle fonction, vous pouvez essayer cette méthode:

List<String> myList = new ArrayList<String>(); //The list you're checking
String wordToFind = "Test"; //or scan.nextLine() or whatever you're checking

//If your list has mix of uppercase and lowercase letters letters create a copy...
List<String> copyList = new ArrayList<String>();
for(String copyWord : myList){
   copyList.add(copyWord.toLowerCase());
}

for(String myWord : copyList){
   if(copyList.contains(wordToFind.toLowerCase()){
      //do something
   }
}
0
Marek Rajtar

Je le ferais comme si:

public boolean isStringInList(final List<String> myList, final String stringToFind) {
    return myList.stream().anyMatch(s -> s.equalsIgnoreCase(stringToFind));
}  
0
Mauro

Ne réinventez pas la roue. Utilisez des API bien testées. Pour votre usage, utilisez Apache Commons StringUtils

Depuis la Javadoc: Compare la chaîne donnée à une variable CharSequences de searchStrings Renvoyant la valeur true si la chaîne est égale à l'une des chaînes searchStrings, en ignorant la casse

import org.Apache.commons.lang3.StringUtils;
...
StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
StringUtils.equalsAnyIgnoreCase(null, null, null)    = true
StringUtils.equalsAnyIgnoreCase(null, "abc", "def")  = false
StringUtils.equalsAnyIgnoreCase("abc", null, "def")  = false
StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true
0
Cengiz

C'est un meilleur moyen de convertir votre élément de liste en minuscule. Après la conversion, vous utiliserez la méthode contient. comme

List<String> name_list = new ArrayList<>();
name_list.add("A");
name_list.add("B");

Créer une liste minuscule en utilisant le name_list créé ci-dessus

List<String> name_lowercase_list = new ArrayList<>();
for(int i =0 ; i<name_list.size(); i++){
 name_lowercase_list.add(name_list.get(i).toLowerCase().toString()); 
}

for(int i =0 ; i<name_list.size(); i++){
  String lower_case_name =  name_list.get(i).toLowerCase().toString();
  if(name_list.get(i).contains(your compare item) ||
   name_lowercase_list.get(i).contains(your compare item) ){
     //this will return true
   }
}
0
Farhan Ghaffar