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.
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.
Si vous utilisez Java 8
List<String> list = new ArrayList<>();
boolean containsSearchStr = list.stream().anyMatch("search_value"::equalsIgnoreCase);
private boolean containsIgnoreCase(List<String> list, String soughtFor) {
for (String current : list) {
if (current.equalsIgnoreCase(soughtFor)) {
return true;
}
}
return false;
}
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:
Collator
et CollationKey
.boolean matches(String fragment)
. Demandez au DVD de vous dire à quoi il correspond.title
de la table DVD
de cette façon. Utilisez JDBC ou Hibernate ou JPA ou Spring Data, selon votre choix.Apache Lucene
et éventuellement Apache Solr
.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.
En Java 8, vous pouvez utiliser l'interface Stream:
return dvdList.stream().anyMatch(d -> d.getTitle().equalsIgnoreCase("SomeTitle"));
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;
}
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 String
s 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
}
}
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;
}
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!");
}