'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.
Solution 1:[1]
If you're using Java 8
List<String> list = new ArrayList<>();
boolean containsSearchStr = list.stream().anyMatch("search_value"::equalsIgnoreCase);
Solution 2:[2]
private boolean containsIgnoreCase(List<String> list, String soughtFor) {
for (String current : list) {
if (current.equalsIgnoreCase(soughtFor)) {
return true;
}
}
return false;
}
Solution 3:[3]
In Java 8 you can use the Stream interface:
return dvdList.stream().anyMatch(d -> d.getTitle().equalsIgnoreCase("SomeTitle"));
Solution 4:[4]
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:
- Learn the
CollatorandCollationKeyclasses. - 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. - Use a database. If it supports case-insensitive collations, declare the
titlecolumn of theDVDtable that way. Use JDBC or Hibernate or JPA or Spring Data, whichever you choose. - If the database supports advanced text search, like Oracle, use that.
- Back in the Java world, use
Apache Luceneand possiblyApache Solr. - 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 5:[5]
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 6:[6]
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 7:[7]
private fun compareCategory(
categories: List<String>?,
category: String
) = categories?.any { it.equals(category, true) } ?: false
Solution 8:[8]
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 9:[9]
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 10:[10]
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 11:[11]
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 12:[12]
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 13:[13]
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 14:[14]
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 15:[15]
For Java 8+, I recommend to use following library method.
org.apache.commons.lang3.StringUtils
list.stream()
.filter(text -> StringUtils.containsIgnoreCase(text, textToSearch))
Solution 16:[16]
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);
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
