[java] Option to ignore case with .contains method?

Is there an option to ignore case with .contains() method?

I have an ArrayList of DVD object. Each DVD object has a few elements, one of them is a title. And I have a method that searches for a specific title. It works, but I'd like it to be case insensitive.

This question is related to java list arraylist

The answer is


Kotlin Devs, go with any / none

private fun compareCategory(
        categories: List<String>?,
        category: String
    ) = categories?.any { it.equals(category, true) } ?: false

This probably isn't the best way for your particular problem, but you can use the String.matches(String regex) method or the matcher equivalent. We just need to construct a regular expression from your prospective title. Here it gets complex.

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

But this is inefficient, and it's being done purely in Java. You would do better to try one of these techniques:

  1. Learn the Collator and CollationKey classes.
  2. If you have no choice but to stay in the Java world, add a method to DVD, boolean matches(String fragment). Have the DVD tell you what it matches.
  3. Use a database. If it supports case-insensitive collations, declare the title column of the DVD table that way. Use JDBC or Hibernate or JPA or Spring Data, whichever you choose.
  4. If the database supports advanced text search, like Oracle, use that.
  5. Back in the Java world, use Apache Lucene and possibly Apache Solr.
  6. Use a language tuned for case-insensitive matches.

If you can wait until Java 8, use lambda expressions. You can avoid the Pattern and Matcher class that I used above by building the regex this way:

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

But this compiles the pattern too many times. What about lower-casing everything?

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

Congratulations; you've just discovered the Turkish problem. Unless you state the locale in toLowerCase, Java finds the current locale. And the lower-casing is slow because it has to take into account the Turkish dotless i and dotted I. At least you have no patterns and no matchers.


If you are looking for contains & not equals then i would propose below solution. Only drawback is if your searchItem in below solution is "DE" then also it would match

    List<String> list = new ArrayList<>();
    public static final String[] LIST_OF_ELEMENTS = { "ABC", "DEF","GHI" };
    String searchItem= "def";

     if(String.join(",", LIST_OF_ELEMENTS).contains(searchItem.toUpperCase())) {
            System.out.println("found element");
            break;
    }

With a null check on the dvdList and your searchString

    if (!StringUtils.isEmpty(searchString)) {
        return Optional.ofNullable(dvdList)
                       .map(Collection::stream)
                       .orElse(Stream.empty())
                       .anyMatch(dvd >searchString.equalsIgnoreCase(dvd.getTitle()));
      }

You can't guarantee that you're always going to get String objects back, or that the object you're working with in the List implements a way to ignore case.

If you do want to compare Strings in a collection to something independent of case, you'd want to iterate over the collection and compare them without case.

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 boolean containsIgnoreCase(List<String> list, String soughtFor) {
    for (String current : list) {
        if (current.equalsIgnoreCase(soughtFor)) {
            return true;
        }
    }
    return false;
}

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

If you're using Java 8

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

boolean containsSearchStr = list.stream().anyMatch("search_value"::equalsIgnoreCase);

For Java 8, You can have one more solution like below

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

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

In Java 8 you can use the Stream interface:

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

The intuitive solution to transform both operands to lower case (or upper case) has the effect of instantiating an extra String object for each item which is not efficient for large collections. Also, regular expressions are an order of magnitude slower than simple characters comparison.

String.regionMatches() allows to compare two String regions in a case-insensitive way. Using it, it's possible to write an efficient version of a case-insensitive "contains" method. The following method is what I use; it's based on code from 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;
}

I know I'm a little late to the party but in Kotlin you can easily use:

fun Collection<String>.containsIgnoreCase(item: String) = any {
    it.equals(item, ignoreCase = true)
}


val list = listOf("Banana")

println(list.contains("banana"))
println(list.containsIgnoreCase("BaNaNa"))

You can apply little trick over this.
Change all the string to same case: either upper or lower case
For C# Code:

List searchResults = sl.FindAll(s => s.ToUpper().Contains(seachKeyword.ToUpper()));

For Java Code:

import java.util.*; 

class Test
{
    public static void main(String[] args)
    {
        String itemCheck="check";
        ArrayList<String> listItem =new ArrayList<String>();
        listItem.add("Check");
        listItem.add("check");
        listItem.add("CHeck");
        listItem.add("Make");
        listItem.add("CHecK");
        for(String item :listItem)
        {
            if(item.toUpperCase().equals(itemCheck.toUpperCase()))
            {
                System.out.println(item);
            }
        }

    }

}

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to list

Convert List to Pandas Dataframe Column Python find elements in one list that are not in the other Sorting a list with stream.sorted() in Java Python Loop: List Index Out of Range How to combine two lists in R How do I multiply each element in a list by a number? Save a list to a .txt file The most efficient way to remove first N elements in a list? TypeError: list indices must be integers or slices, not str Parse JSON String into List<string>

Examples related to arraylist

Adding null values to arraylist How to iterate through an ArrayList of Objects of ArrayList of Objects? Dynamically adding elements to ArrayList in Groovy How to replace existing value of ArrayList element in Java How to remove the last element added into the List? How to append elements at the end of ArrayList in Java? Removing Duplicate Values from ArrayList How to declare an ArrayList with values? In Java, can you modify a List while iterating through it? Load arrayList data into JTable