web-dev-qa-db-fra.com

Option pour ignorer la casse avec la méthode .contains?

Existe-t-il une option permettant d’ignorer la casse avec la méthode .contains()?

J'ai un ArrayList d'objet DVD. Chaque objet DVD contient quelques éléments, l'un d'entre eux étant un titre. Et j'ai une méthode qui recherche un titre spécifique. Cela fonctionne, mais j'aimerais que ce soit insensible à la casse. 

33
trama

J'imagine que vous voulez dire ignorer la casse lors d'une recherche dans une chaîne?

Je ne connais aucun, mais vous pouvez essayer de convertir la chaîne pour rechercher en bas ou en majuscule, puis rechercher.

// s is the String to search into, and seq the sequence you are searching for.
bool doesContain = s.toLowerCase().contains(seq);

Edit: Comme Ryan Schipper l’a suggéré, vous pouvez également (et serait probablement mieux) faire seq.toLowerCase (), en fonction de votre situation.

25
Spam

Si vous utilisez Java 8

List<String> list = new ArrayList<>();

boolean containsSearchStr = list.stream().anyMatch("search_value"::equalsIgnoreCase);
47
Nivas Mane-Patil
private boolean containsIgnoreCase(List<String> list, String soughtFor) {
    for (String current : list) {
        if (current.equalsIgnoreCase(soughtFor)) {
            return true;
        }
    }
    return false;
}
12
Aleksey Antoshkin

Ce n'est probablement pas la meilleure solution pour votre problème particulier, mais vous pouvez utiliser la méthode String.matches(String regex) ou l'équivalent de matcher. Nous avons juste besoin de construire une expression régulière à partir de votre titre éventuel. Ici ça devient complexe.

List<DVD> matchingDvds(String titleFragment) {
    String escapedFragment = Pattern.quote(titleFragment);
    // The pattern may have contained an asterisk, dollar sign, etc.
    // For example, M*A*S*H, directed by Robert Altman.
    Pattern pat = Pattern.compile(escapedFragment, Pattern.CASE_INSENSITIVE);
    List<DVD> foundDvds = new ArrayList<>();
    for (DVD dvd: catalog) {
        Matcher m = pat.matcher(dvd.getTitle());
        if (m.find()) {
            foundDvds.add(dvd);
        }
    }
    return foundDvds;
}

Mais cela est inefficace et cela se fait uniquement en Java. Vous feriez mieux d'essayer l'une de ces techniques:

  1. Apprenez les classes Collator et CollationKey.
  2. Si vous n'avez pas d'autre choix que de rester dans le monde Java, ajoutez une méthode à DVD, boolean matches(String fragment). Demandez au DVD de vous dire à quoi il correspond.
  3. Utilisez une base de données. S'il prend en charge les classements ne respectant pas la casse, déclarez la colonne title de la table DVD de cette façon. Utilisez JDBC ou Hibernate ou JPA ou Spring Data, selon votre choix.
  4. Si la base de données prend en charge la recherche de texte avancée, comme Oracle, utilisez-la.
  5. De retour dans le monde Java, utilisez Apache Lucene et éventuellement Apache Solr.
  6. Utilisez un langage adapté aux correspondances sans distinction de casse.

Si vous pouvez attendre jusqu'à Java 8, utilisez les expressions lambda. Vous pouvez éviter la classe Pattern et Matcher que j'ai utilisée ci-dessus en construisant le regex de cette façon:

   String escapedFragment = Pattern.quote(titleFragment);
   String fragmentAnywhereInString = ".*" + escapedFragment + ".*";
   String caseInsensitiveFragment = "(?i)" + fragmentAnywhereInString;
   // and in the loop, use:
   if(dvd.getTitle().matches(caseInsensitiveFragment)) {
        foundDvds.add(dvd);
    }

Mais cela compile le motif trop de fois. Qu'en est-il de tout ce qui est inférieur?

if (dvd.getTitle().toLowerCase().contains(titleFragment.toLowerCase()))

Toutes nos félicitations; vous venez de découvrir le problème turc. Sauf si vous indiquez les paramètres régionaux dans toLowerCase, Java recherche les paramètres régionaux actuels. Et le bas des caisses est lent car il doit prendre en compte le turc i dotless et le I. pointillé I. Au moins, vous n'avez pas de motifs ni de correspondants.

4
Eric Jablow

En Java 8, vous pouvez utiliser l'interface Stream:

return dvdList.stream().anyMatch(d -> d.getTitle().equalsIgnoreCase("SomeTitle"));
3
Paul Bonneau

La solution intuitive permettant de transformer les deux opérandes en minuscules (ou majuscules) a pour effet d'instancier un objet String supplémentaire pour chaque élément, ce qui n'est pas efficace pour les grandes collections. De plus, les expressions régulières ont un ordre de grandeur plus lent que la simple comparaison de caractères.

String.regionMatches() permet de comparer deux régions String sans tenir compte de la casse. En l'utilisant, il est possible d'écrire une version efficace d'une méthode "contient" insensible à la casse. La méthode suivante est ce que j'utilise; il est basé sur le code d'Apache commons-lang:

public static boolean containsIgnoreCase(final String str, final String searchStr) {
    if (str == null || searchStr == null) {
        return false;
    }
    final int len = searchStr.length();
    final int max = str.length() - len;
    for (int i = 0; i <= max; i++) {
        if (str.regionMatches(true, i, searchStr, 0, len)) {
            return true;
        }
    }
    return false;
}
2
BladeCoder

Vous ne pouvez pas garantir que vous obtiendrez toujours des objets String, ou que l'objet avec lequel vous travaillez dans List implémente un moyen d'ignorer la casse.

Si vous souhaitez comparer Strings dans une collection à quelque chose d'indépendant de la casse, vous souhaitez effectuer une itération sur la collection et les comparer sans casse.

String Word = "Some Word";
List<String> aList = new ArrayList<>(); // presume that the list is populated

for(String item : aList) {
    if(Word.equalsIgnoreCase(item)) {
        // operation upon successful match
    }
}
2
Makoto
 private List<String> FindString(String stringToLookFor, List<String> arrayToSearchIn)
 {
     List<String> ReceptacleOfWordsFound = new ArrayList<String>();

     if(!arrayToSearchIn.isEmpty())
     {
         for(String lCurrentString : arrayToSearchIn)
         {
             if(lCurrentString.toUpperCase().contains(stringToLookFor.toUpperCase())
                 ReceptacleOfWordsFound.add(lCurrentString);
         }
     }
  return ReceptacleOfWordsFound;
 }
0
Br0thazS0ul

Pour Java 8, vous pouvez avoir une solution supplémentaire comme ci-dessous 

List<String> list = new ArrayList<>();
String searchTerm = "dvd";

if(String.join(",", list).toLowerCase().contains(searchTerm)) {
  System.out.println("Element Present!");
}
0
Pavan