ArrayList contains case sensitivity

JavaArraylist

Java Problem Overview


I am currently using the contains method belonging to the ArrayList class for making a search. Is there a way to make this search case insensitive in java? I found that in C# it is possible to use OrdinalIgnoreCase. Is there a java equivalent, or another way to do this? Thanks.

Java Solutions


Solution 1 - Java

You can use this exactly like you'd use any other ArrayList. You can pass this List out to other code, and external code won't have to understand any string wrapper classes.

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;
    }
}

Solution 2 - Java

In Java8, using anyMatch

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

boolean isMatched = list.stream().anyMatch(matchingText::equalsIgnoreCase);

Solution 3 - Java

If you're using Java 8, try:

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

Solution 4 - Java

Traditionally, you can develop your own logic to compare strings held by an ArrayList. There may be several ways to do so like the one shown below.

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

Why shouldn't be used some direct and convenient ways like a SortedSet as shown below with a case insensitive comparator?.

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));

Would compare two different sets ignoring case and return true, in this particular situation and your comparision would work without any issue.

Solution 5 - Java

Looking at the Java API, there is no such method for contains.

But you could do at least two things:

  1. Override the equals method in your ArrayList object with your own, or equalsIgnoreCase(str)

  2. Write your own contains method, which should iterate through your ArrayList entities, and do a manual check.

    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;
    }
    

Solution 6 - Java

Assuming you have an ArrayList<String>

About the only way I can think of to do this would be to create a very light wrapper class around a String and override equals and hashcode to ignore case, leveraging equalsIgnoreCase() where possible. Then you would have an ArrayList<YourString>. It's kinda an ugly idea though.

Solution 7 - Java

You can use IterableUtils and Predicate from 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

Solution 8 - Java

The contains method is based on what the equals method of the objects stored in your ArrayList returns. So yes it is possible if you use objects where equals uses a case insensitive comparison.

So you could for example use a class like this (code might still contain some typos)

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();
  }
}

Solution 9 - Java

ArrayList's contains() method checks equality by calling equals() method on the object you provide (NOT the objects in the array). Therefore, a slightly hackish way is to create a wrapper class around the String object, like this:

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();
	}
}

Then you can use it to perform your test. Example "manual" test case:

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")));
	}
}

Solution 10 - Java

Another 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;
	}
}

contains() method uses indexOf... In this sollution you can also know in where position is the string. list.add("a") -> list.indexOf("A") == 0 or list.indexOf("a") == 0 ..

You should also consider using a Set instead of List.

Solution 11 - Java

For java8

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

For < java8

  • as suggested by Aaron J Lang above
  • Or if you know case of your list ( all upper /all lower ) then convert the search string to appropriate case before comparing

Solution 12 - Java

In my case, as all my strings in the ArrayList are in downcase, I just execute the String.toLowerCase() method on the contains() parameter. Like this:

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

As you can see, you can do the oposite, if yout arrayList has upperCase strings:

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

Using this approach, you do not need to override anything. The exception is in the case when your arrayList have a mix of upper and lower cases.

Solution 13 - Java

I would make it like so:

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

Solution 14 - Java

There's no need to for the additional function, the desired results can be achieved by casting the compared strings to either uppercase or lowercase

(I know this has been suggested in the comments, but not thoroughly provided as an answer)

Ex: Ignores case while filtering the contents of a JList based on the input provided from a 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.
     */
}

Solution 15 - Java

Don't reinvent the wheel. Use well tested APIs. For your purpose use Apache Commons StringUtils.

From the Javadoc: Compares given string to a CharSequences vararg of searchStrings returning true if the string is equal to any of the searchStrings, ignoring case.

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

Solution 16 - Java

1st way

  List<String> list = Arrays.asList("XYZ", "ABC");
    String matchingText = "XYZ1";
        boolean isMatched = list.stream().anyMatch(matchingText::equalsIgnoreCase);
        System.out.println(isMatched);

2nd way

List<String> list1= Arrays.asList("XYZ", "ABC");
String searchStr = "abC";
boolean containsSearchStr = list1.stream().filter(searchStr::equalsIgnoreCase).findFirst().isPresent();
System.out.println(containsSearchStr);

Solution 17 - Java

Its a best way to convert your list item into lowercase. After convert you will use contain method. like

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

Create lowercase list using above created name_list

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
   }
}

Solution 18 - Java

If you don't want to create a new function, you can try this method:

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
   }
}

Solution 19 - Java

While the question was asked specifically about Java, the same issue exists in Kotlin.

You can use an extension for this that applies to List, Array and ArrayList

fun Array<String>.contains(element: String, ignoreCase: Boolean): Boolean {
  forEach { if (it.equals(element, ignoreCase = ignoreCase)) return true }
  return false
}

Solution 20 - Java

By using compareToIgnoreCase, http://docs.oracle.com/javase/1.3/docs/api/java/lang/String.html#compareToIgnoreCase%28java.lang.String%29 you should be able to do what you want!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohnView Question on Stackoverflow
Solution 1 - JavaAaron J LangView Answer on Stackoverflow
Solution 2 - JavaFree-MindedView Answer on Stackoverflow
Solution 3 - JavaJosh MView Answer on Stackoverflow
Solution 4 - JavaLionView Answer on Stackoverflow
Solution 5 - JavaHeavenAgainView Answer on Stackoverflow
Solution 6 - JavarfeakView Answer on Stackoverflow
Solution 7 - JavabpedrosoView Answer on Stackoverflow
Solution 8 - JavaRobinView Answer on Stackoverflow
Solution 9 - JavaSerammeView Answer on Stackoverflow
Solution 10 - JavaRogel GarciaView Answer on Stackoverflow
Solution 11 - JavaOm.View Answer on Stackoverflow
Solution 12 - JavaBruno MoraisView Answer on Stackoverflow
Solution 13 - JavaMauroView Answer on Stackoverflow
Solution 14 - JavaJReynView Answer on Stackoverflow
Solution 15 - JavaCengizView Answer on Stackoverflow
Solution 16 - JavaNaveen PandeyView Answer on Stackoverflow
Solution 17 - JavaFarhan GhaffarView Answer on Stackoverflow
Solution 18 - JavaMarek RajtarView Answer on Stackoverflow
Solution 19 - JavaDevinMView Answer on Stackoverflow
Solution 20 - JavaJeremy DView Answer on Stackoverflow