Option to ignore case with .contains method?

JavaListArraylist

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

If you're using Java 8

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

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

Solution 2 - Java

I'm guessing you mean ignoring case when searching in a string?

I don't know any, but you could try to convert the string to search into either to lower or to upper case, then search.

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

Edit: As Ryan Schipper suggested, you can also (and probably would be better off) do seq.toLowerCase(), depending on your situation.

Solution 3 - Java

private boolean containsIgnoreCase(List<String> list, String soughtFor) {
    for (String current : list) {
        if (current.equalsIgnoreCase(soughtFor)) {
            return true;
        }
    }
    return false;
}

Solution 4 - Java

In Java 8 you can use the Stream interface:

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

Solution 5 - Java

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.

Solution 6 - Java

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

Solution 7 - Java

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

Solution 8 - Java

> Kotlin Devs, go with any / none

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

Solution 9 - Java

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

Solution 10 - Java

It's very simple using the power of Kotlin's extension function, this answer may help Java and Kotlin developers.

inline fun List<String>.contains(text: String, ignoreCase: Boolean = false) = this.any { it.equals(text, ignoreCase) }

// Usage
list.contains("text", ignoreCase = true)

Solution 11 - Java

You can replace contains() for equalsIgnoreCase using stream() as below

    List<String> names = List.of("One","tWo", "ThrEe", "foUR", "five", "Six", "THREE");
    boolean contains = names.stream().filter(i -> i.equalsIgnoreCase("three")).collect(Collectors.toList()).size() > 0;

Solution 12 - Java

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

Solution 13 - Java

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

Solution 14 - Java

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

Solution 15 - Java

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

Solution 16 - Java

For Java 8+, I recommend to use following library method.

> org.apache.commons.lang3.StringUtils

list.stream()
   .filter(text -> StringUtils.containsIgnoreCase(text, textToSearch))

Solution 17 - Java

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

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
QuestiontramaView Question on Stackoverflow
Solution 1 - JavaNivas Mane-PatilView Answer on Stackoverflow
Solution 2 - JavaSpamView Answer on Stackoverflow
Solution 3 - JavaOleksii AntoshkinView Answer on Stackoverflow
Solution 4 - JavaPaul BonneauView Answer on Stackoverflow
Solution 5 - JavaEric JablowView Answer on Stackoverflow
Solution 6 - JavaDDsixView Answer on Stackoverflow
Solution 7 - JavaMakotoView Answer on Stackoverflow
Solution 8 - JavaAnoop M MaddasseriView Answer on Stackoverflow
Solution 9 - JavaBladeCoderView Answer on Stackoverflow
Solution 10 - JavaGooglianView Answer on Stackoverflow
Solution 11 - JavaHarshad PanmandView Answer on Stackoverflow
Solution 12 - JavaThrowableExceptionView Answer on Stackoverflow
Solution 13 - JavaBr0thazS0ulView Answer on Stackoverflow
Solution 14 - JavaPavanView Answer on Stackoverflow
Solution 15 - Javauser1416932View Answer on Stackoverflow
Solution 16 - JavarelativelyPrimeView Answer on Stackoverflow
Solution 17 - JavaDipitakView Answer on Stackoverflow