Возможность игнорировать случай с методом .contains?

Есть ли возможность игнорировать регистр с помощью метода .contains()?

У меня есть ArrayList объект DVD. Каждый объект DVD имеет несколько элементов, один из которых является заголовком. И у меня есть метод, который ищет конкретный заголовок. Это работает, но я хотел бы, чтобы это было без учета регистра.

Ответ 1

Я предполагаю, что вы имеете в виду игнорировать случай при поиске в строке?

Я не знаю, но вы можете попытаться преобразовать строку для поиска в нижний или верхний регистр, затем выполните поиск.

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

Изменить: Как предложил Райан Шиппер, вы также можете (и, вероятно, лучше) сделать seq.toLowerCase(), в зависимости от вашей ситуации.

Ответ 2

Если вы используете Java 8

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

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

Ответ 3

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

Ответ 4

Это, вероятно, не самый лучший способ для вашей конкретной проблемы, но вы можете использовать метод String.matches(String regex) или эквивалент сопряжения. Нам просто нужно построить регулярное выражение из вашего предполагаемого названия. Здесь он становится сложным.

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

Но это неэффективно, и это делается исключительно на Java. Вам лучше попробовать один из этих методов:

  • Изучите классы Collator и CollationKey.
  • Если у вас нет выбора, кроме как оставаться в мире Java, добавьте метод на DVD, boolean matches(String fragment). Попросите DVD рассказать вам, что он соответствует.
  • Использовать базу данных. Если он поддерживает нечувствительные к регистру сопоставления, объявите столбец title таблицы DVD таким образом. Используйте JDBC или Hibernate или JPA или Spring Данные, в зависимости от того, что вы выберете.
  • Если база данных поддерживает расширенный текстовый поиск, например Oracle, используйте это.
  • Вернитесь в мир Java, используйте Apache Lucene и, возможно, Apache Solr.
  • Используйте язык, настроенный для нечувствительных к регистру совпадений.

Если вы можете дождаться Java 8, используйте лямбда-выражения. Вы можете избежать класса Pattern и Matcher, который я использовал выше, создав регулярное выражение следующим образом:

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

Но это скомпилирует шаблон слишком много раз. Что о нижнем корпусе все?

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

Поздравляем; вы только что обнаружили турецкую проблему. Если вы не укажете локаль в toLowerCase, Java найдет текущую локаль. И нижний корпус медленный, потому что он должен учитывать турецкий бесцеремонный я и пунктир I. По крайней мере, у вас нет паттернов и нет совпадений.

Ответ 5

В Java 8 вы можете использовать интерфейс Stream:

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

Ответ 6

Вы не можете гарантировать, что вы всегда будете получать объекты String назад или что объект, с которым вы работаете в List, реализует способ игнорировать случай.

Если вы хотите сравнить String в коллекции с чем-то независящим от случая, вам нужно выполнить итерацию по коллекции и сравнить их без необходимости.

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

Ответ 7

Интуитивное решение для преобразования обоих операндов в нижний регистр (или в верхний регистр) приводит к созданию экземпляра дополнительного объекта String для каждого элемента, который неэффективен для больших коллекций. Кроме того, регулярные выражения на порядок медленнее, чем сравнение простых символов.

String.regionMatches() позволяет сравнивать две области строк без учета регистра. Используя его, можно написать эффективную версию метода "содержит" без учета регистра. Следующий метод - это то, что я использую; он основан на коде из 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;
}

Ответ 8

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

Ответ 9

Для Java 8 у вас может быть еще одно решение, например ниже

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

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

Ответ 10

Если вы ищете содержит & не равно, то я бы предложил решение ниже. Единственным недостатком является то, что если ваш searchItem в приведенном ниже решении "DE", то он также будет соответствовать

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

Ответ 11

Вы можете применить небольшой трюк к этому.
Измените всю строку на тот же случай: либо верхний, либо нижний регистр
Для кода С#:

Список поискаРезультаты = sl.FindAll(s = > s.ToUpper(). Состояния (seachKeyword.ToUpper()));

Код Java:

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

    }

}