关于java:ArrayList包含区分大小写

ArrayList contains case sensitivity

我目前正在使用属于ArrayList类的contains方法进行搜索。 有没有办法使此搜索在Java中不区分大小写? 我发现在C#中可以使用OrdinalIgnoreCase。 是否有等效的Java或另一种方法?
谢谢。


您可以像使用其他任何ArrayList一样使用它。您可以将该列表传递给其他代码,并且外部代码不必了解任何字符串包装器类。

1
2
3
4
5
6
7
8
9
10
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;
    }
}


在Java8中,使用anyMatch

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

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


如果您使用的是Java 8,请尝试:

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


传统上,您可以开发自己的逻辑来比较ArrayList持有的字符串。可能有以下几种方式可以做到这一点。

1
2
3
4
5
6
7
8
9
10
11
public boolean containsCaseInsensitive(String strToCompare, ArrayList<String>list)
{
    for(String str:list)
    {
        if(str.equalsIgnoreCase(strToCompare))
        {
            return(true);
        }
    }
    return(false);
}

为什么不应该使用一些直接且方便的方式,例如不区分大小写的比较器使用如下所示的SortedSet?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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));

在这种特殊情况下,将比较两个不同的集合而忽略大小写并返回true,并且您的比较将毫无问题地进行。


看一下Java API,没有包含这种方法。

但是您至少可以做两件事:

  • 用您自己的或equalsIgnoreCase(str)覆盖ArrayList对象中的equals方法
  • 编写您自己的contains方法,该方法应遍历ArrayList实体,并进行手动检查。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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;
    }

  • 假设您有一个ArrayList

    我能想到的唯一方法是在String周围创建一个非常轻巧的包装类,并覆盖equals和hashcode以忽略大小写,并尽可能利用equalsIgnoreCase()。然后,您将得到一个ArrayList。不过,这有点丑陋。


    您可以使用collections4(apache)中的IterableUtils和Predicate。

    1
    2
    3
    4
    5
    6
    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


    对于java8

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

    对于

    • 正如上述Aaron J Lang所建议
    • 或者,如果您知道列表的大小写(全部大写/全部小写),则在比较之前将搜索字符串转换为适当的大小写

    contains方法基于ArrayList中存储的对象的equals方法返回的内容。因此,可以,如果您使用equals使用不区分大小写的比较的对象。

    因此,例如,您可以使用这样的类(代码可能仍包含一些错字)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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();
      }
    }


    就我而言,由于ArrayList中的所有字符串均为小写形式,因此我只需对contains()参数执行String.toLowerCase()方法。像这样:

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

    如您所见,如果arrayList具有upperCase字符串,则可以做相反的事情:

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

    使用这种方法,您不需要覆盖任何内容。当您的arrayList包含大小写混合时,例外。


    另一个解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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()方法使用indexOf ...在这种解决方案中,您还可以知道字符串的位置。 list.add("a")-> list.indexOf("A") == 0list.indexOf("A") == 0 ..

    您还应该考虑使用Set而不是List。


    ArrayList的contains()方法通过在您提供的对象上调用equals()方法(而不是数组中的对象)来检查是否相等。因此,一种有点怪异的方法是围绕String对象创建一个包装器类,如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    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();
        }
    }

    然后,您可以使用它来执行测试。示例"手动"测试用例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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")));
        }
    }


    我会这样:

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

    不要重新发明轮子。 使用经过良好测试的API。 为了您的目的,请使用Apache Commons StringUtils。

    从Javadoc:
    将给定的字符串与searchStrings的CharSequences变量比较
    如果字符串等于任何searchStrings,则返回true,忽略大小写。

    1
    2
    3
    4
    5
    6
    7
    8
    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


    不需要附加功能,可以通过将比较的字符串转换为大写或小写字母来实现所需的结果

    (我知道这已在评论中提出,但并未提供完整答案)

    例如:根据JTextField提供的输入过滤JList内容时忽略大小写:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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.
         */

    }

    这是将列表项转换为小写字母的最佳方法。转换后,您将使用包含方法。喜欢

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

    使用上面创建的name_list创建小写列表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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
       }
    }


    第一种方式

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

    第二路

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

    如果您不想创建新函数,可以尝试以下方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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
       }
    }

    通过使用compareToIgnoreCase(http://docs.oracle.com/javase/1.3/docs/api/java/lang/String.html#compareToIgnoreCase%28java.lang.String%29),您应该能够执行想要的操作!