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.
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;
}
}
Si vous utilisez Java 8, essayez:
List<String> list = ...;
String searchStr = ...;
boolean containsSearchStr = list.stream().filter(s -> s.equalsIgnoreCase(searchStr)).findFirst().isPresent();
En Java8, en utilisant anyMatch
List<String> list = Arrays.asList("XYZ", "ABC");
String matchingText = "xYz";
boolean isMatched = list.stream().anyMatch(matchingText::equalsIgnoreCase);
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.
En regardant le API Java , il n’existe pas de telle méthode pour contient.
Mais vous pouvez faire au moins deux choses:
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;
}
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.
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
Pour Java8
list.stream (). anyMatch (s -> s.equalsIgnoreCase (yourString))
Pour <Java8
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();
}
}
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.
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")));
}
}
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.
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.
*/
}
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
}
}
Je le ferais comme si:
public boolean isStringInList(final List<String> myList, final String stringToFind) {
return myList.stream().anyMatch(s -> s.equalsIgnoreCase(stringToFind));
}
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
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
}
}