[英]ArrayList contains case sensitivity
我目前正在使用属于 ArrayList 类的 contains 方法进行搜索。 有没有办法在java中使这个搜索不区分大小写? 我发现在 C# 中可以使用 OrdinalIgnoreCase。 是否有 java 等价物,或其他方法来做到这一点? 谢谢。
您可以像使用任何其他 ArrayList 一样使用它。 您可以将此 List 传递给其他代码,而外部代码不必了解任何字符串包装类。
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
List<String> list = Arrays.asList("XYZ", "ABC");
String matchingText = "xYz";
boolean isMatched = list.stream().anyMatch(matchingText::equalsIgnoreCase);
如果您使用的是 Java 8,请尝试:
List<String> list = ...;
String searchStr = ...;
boolean containsSearchStr = list.stream().filter(s -> s.equalsIgnoreCase(searchStr)).findFirst().isPresent();
传统上,您可以开发自己的逻辑来比较ArrayList
持有的字符串。 可能有几种方法可以做到这一点,如下所示。
public boolean containsCaseInsensitive(String strToCompare, ArrayList<String>list)
{
for(String str:list)
{
if(str.equalsIgnoreCase(strToCompare))
{
return(true);
}
}
return(false);
}
为什么不应该使用一些直接和方便的方法,例如 SortedSet,如下所示, 不区分大小写的比较器?。
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 ,对于 contains 没有这样的方法。
但是你至少可以做两件事:
编写您自己的 contains 方法,该方法应该遍历您的 ArrayList 实体,并进行手动检查。
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>
我能想到的唯一方法是围绕 String 创建一个非常轻的包装类并覆盖 equals 和 hashcode 以忽略大小写,尽可能利用equalsIgnoreCase()
。 然后你会有一个ArrayList<YourString>
。 不过,这有点丑陋的想法。
您可以使用 collections4 (apache) 中的 IterableUtils 和 Predicate。
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))
对于 < java8
就我而言,由于 ArrayList 中的所有字符串都是小写的,因此我只执行 String。 contains() 参数上的toLowerCase()方法。 像这样:
If (yourArrayList.contains (parameterInput.toLowerCase()) {
// your code here
}
如您所见,如果 arrayList 具有 upperCase 字符串,则可以执行相反的操作:
If (yourArrayList.contains (parameterInput.toUpperCase ()) {
// your code here
}
使用这种方法,您不需要覆盖任何内容。 例外情况是当您的 arrayList 混合使用大写和小写时。
我会让它像这样:
public boolean isStringInList(final List<String> myList, final String stringToFind) {
return myList.stream().anyMatch(s -> s.equalsIgnoreCase(stringToFind));
}
contains
方法基于存储在ArrayList
中的对象的equals
方法返回的内容。 所以是的,如果您使用equals
使用不区分大小写比较的对象,则是可能的。
例如,您可以使用这样的类(代码可能仍包含一些拼写错误)
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() 方法通过对您提供的对象(不是数组中的对象)调用 equals() 方法来检查相等性。 因此,稍微有点hackish 的方法是围绕String 对象创建一个包装类,如下所示:
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();
}
}
然后您可以使用它来执行您的测试。 “手动”测试用例示例:
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")));
}
}
另一种解决方案:
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") == 0
或list.indexOf("a") == 0
..
您还应该考虑使用 Set 而不是 List。
不需要额外的功能,可以通过将比较的字符串转换为大写或小写来实现所需的结果
(我知道这已在评论中提出,但没有作为答案彻底提供)
例如:根据 JTextField 提供的输入过滤 JList 的内容时忽略大小写:
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.
*/
}
不要重新发明轮子。 使用经过良好测试的 API。 出于您的目的,请使用Apache Commons StringUtils 。
来自 Javadoc:将给定的字符串与 searchStrings 的 CharSequences vararg 进行比较,如果字符串等于任何一个 searchStrings,则返回 true,忽略大小写。
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
第一种方式
List<String> list = Arrays.asList("XYZ", "ABC");
String matchingText = "XYZ1";
boolean isMatched = list.stream().anyMatch(matchingText::equalsIgnoreCase);
System.out.println(isMatched);
第二种方式
List<String> list1= Arrays.asList("XYZ", "ABC");
String searchStr = "abC";
boolean containsSearchStr = list1.stream().filter(searchStr::equalsIgnoreCase).findFirst().isPresent();
System.out.println(containsSearchStr);
这是将列表项转换为小写的最佳方式。 转换后,您将使用包含方法。 喜欢
List<String> name_list = new ArrayList<>();
name_list.add("A");
name_list.add("B");
使用上面创建的name_list
创建小写列表
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
}
}
如果不想新建函数,可以试试这个方法:
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
}
}
虽然这个问题是专门针对 Java 提出的,但 Kotlin 中也存在同样的问题。
您可以为此使用适用于 List、Array 和 ArrayList 的扩展名
fun Array<String>.contains(element: String, ignoreCase: Boolean): Boolean {
forEach { if (it.equals(element, ignoreCase = ignoreCase)) return true }
return false
}
通过使用 compareToIgnoreCase, http://docs.oracle.com/javase/1.3/docs/api/java/lang/String.html#compareToIgnoreCase%28java.lang.String%29你应该能够做你想做的事!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.