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

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

谢谢。

您是否需要维护列表中字符串的大小写,还是可以全部将它们都小写?

我需要保持相同的情况。

如果在原始情况下也需要返回String,则contains()仅有助于指示列表中存在该字符串。 HashMap可以在给定大写或小写字符串的情况下检索原始字符串,并且具有更好的搜索特性(但不会保留字符串的原始顺序)。

感谢大家的投入,现在我需要决定要使用哪种解决方案。 再次感谢。

这些年来,我简直不敢相信Java没有做到这一点的简便方法。

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

public class CustomStringList3 extends ArrayList {

@Override

public boolean contains(Object o) {

String paramStr = (String)o;

for (String s : this) {

if (paramStr.equalsIgnoreCase(s)) return true;

}

return false;

}

}

这假定插入列表后不需要原始大小写。这是可能的。这取决于OP的用例。或者,并行维护第二个列表。一个使用原始数据,第二个仅使用小写。

@rfeak非常正确! Kinda不好意思我错过了。事后看来,Id使用带有小写字符串键和原始字符串值的映射

@rfeak最后发表了您的第二个想法

@owlstead包装字符串还需要两个对象,即字符串和包装器

只是现在就集思广益,好玩,我确定我们有OP的不错选择。您是否可以像这样子类化,但是可以代替重写add()和get()来使用equalsIgnoreCase()吗?理想的情况是,使用相同的存储空间,保留原始String的内容/顺序,保留String参数(相对于我的想法),然后简单地实例化其他List实现。

@rfeak天才!我现在就放弃

@rfeak怎么样?原始方法是否会遍历整个列表?如果有更快的方法,我不会降低性能。

@AaronJLang-我认为就可以了。看起来很干净。

@owlstead我同意,但是rfeak和我想出了一个更好的解决方案,零开销。查看我的修改后答案

亚伦,如果您对同一问题有不同的答案:请将它们作为单独的答案发布。这使得讨论变得不可能。最后的评论完全是关于Map解决方案的。不要害怕错误的答案,只需将它们标记为这样,用户就可以从可能的解决方案列表中删除它们。

@owlstead我从未考虑过针对同一问题发布多个单独的答案。将来会这样,谢谢:)

我认为这是非常糟糕的解决方案,因为它破坏了List#contains的现有合同。如果确实确实需要在List实例本身上存在功能,则应将其实现为新方法。即containsIgnoreCase。

在Java8中,使用anyMatch

List list = Arrays.asList("XYZ","ABC");

String matchingText ="xYz";

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

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

List list = ...;

String searchStr = ...;

boolean containsSearchStr = list.stream().filter(s -> s.equalsIgnoreCase(searchStr)).findFirst().isPresent();

我知道它很旧,但是您也可以使用anyMatch()代替filter()。findFirst()。isPresent()

作为主要的Android开发人员,我仍然倾向于避免使用Java 8特定的API,而是更喜欢stackoverflow.com/a/8751546/1815624

在下面的anyMatch示例中查看@ shreshtt-bhatt答案

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

public boolean containsCaseInsensitive(String strToCompare, ArrayListlist)

{

for(String str:list)

{

if(str.equalsIgnoreCase(strToCompare))

{

return(true);

}

}

return(false);

}

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

Set a = new TreeSet(String.CASE_INSENSITIVE_ORDER);

a.add("A");

a.add("B");

a.add("C");

Set b = new TreeSet(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实体,并进行手动检查。

ArrayList list = new ArrayList();

...

containsIgnoreCase("a", list);

public boolean containsIgnoreCase(String str, ArrayList list){

for(String i : list){

if(i.equalsIgnoreCase(str))

return true;

}

return false;

}

有时候,简单的答案是最好的,感谢您的输入和欢迎,并提出了建议。

这类似于对列表进行相同操作的答案stackoverflow.com/a/24829584/1815624

假设您有一个ArrayList

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

+1,但我不同意您的最后一句话:几乎不是该应用程序的丑陋解决方案。

@AaronJLang-我评论了您的答案。这取决于是否需要原始案例。是的,这可能会更容易。取决于OP的用例。

@Zychin-嘿。在我自己编写代码之前,Id很丑陋,可以去Guava或Commons Lang中查找更好的解决方案。 :)

不想成为一个失败者,但是扩展List会比扩展/包装所有字符串更简单/更有效/更兼容吗?

@AaronJLang-我认为这两种解决方案都可以完成工作。取决于他们最满意的OP。正如我最初表达的那样,我对自己的解决方案甚至不满意:)

您实际上不必将ArrayList定义为ArrayList ,可以安全地将其声明为ArrayList 并仅将YourString用作ArrayList.contains()的参数(因为它接受任何对象,不仅接受指定的泛型类型, )。这样,您在常规访问期间不必解开ArrayLists对象。

@Seramme打破了等式的对称性要求,您不应那样走

使用此解决方案并使用HashSet而不是ArrayList将是合乎逻辑的(但前提是列表项的顺序无关紧要)。重构为Set也是不重写contains()的一个很好的理由,因为它将始终使用O(N / 2)进行搜索

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

List pformats= Arrays.asList("Test","tEst2","tEsT3","TST4");

Predicate 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使用不区分大小写的比较的对象。

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

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

}

}

所有charSequences(即区分大小写有意义的任何东西)都具有区分大小写的equals()方法,不是吗?

也许添加吸气剂并使用o.equalsIgnoreCase(contents)代替o.toUpperCase().equals(contents.toUpperCase())? equalsIgnoreCase()可以得到更好的优化,并且可能不需要为两个大写字符串分配对象。

@owlstead可以肯定,吸气剂会很好,但不需要说明我的观点。 equalsIgnoreCase确实是一种改进,我将相应地编辑我的回答

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

If (yourArrayList.contains (parameterInput.toLowerCase()) {

// your code here

}

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

If (yourArrayList.contains (parameterInput.toUpperCase ()) {

// your code here

}

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

另一个解决方案:

public class IgnorecaseList extends ArrayList{

@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。

contains()在API中未指定它使用indexOf(),因此您不能为此使用它。如果采用contains()和indexOf()的方式,则您可能应该覆盖两者,并希望不会定义其他任何需要兼容性的方法。我认为,这将其排除为可靠的解决方案。

我同意。固定。

ArrayList的contains()方法通过在您提供的对象上调用equals()方法(而不是数组中的对象)来检查是否相等。因此,一种有点怪异的方法是围绕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 a = new ArrayList();

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

}

}

如果覆盖等于,则应覆盖hashCode。

@rogelware是的,尽管如果您仅将InsensitiveStringComparable用作内部"抛出"类,专门用于不区分大小写的ArrayList搜索,则不必覆盖hashCode,因为ArrayList不会使用它(假设与例如HashMap一起使用)

如果列表使用字符串与InsensitiveStringComparable进行比较而不是相反,则将不起作用。

@Seramme可能是正确的,但非常明显的优化方法是将对象放入HashSet或HashMap中,从而破坏代码。许多静态验证器(例如CheckStyle和FindBugs)会很乐意将其标记为问题。最重要的是,将来可以重写contains()方法,以在equals()之前测试hashCode()的相等性,没有什么反对的。只是不要去那里。

@owlstead是的,非常有效的参数。我已经编辑了原始答案以反映这一点。

不幸的是,您的equals()方法和hashCode()方法都不符合规范。检查Robin的答案以获得更好的实现。

我会这样:

public boolean isStringInList(final List myList, final String stringToFind) {

return myList.stream().anyMatch(s -> s.equalsIgnoreCase(stringToFind));

}

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

从Javadoc:

将给定的字符串与searchStrings的CharSequences变量比较

如果字符串等于任何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 ?

@ kio21您必须将列表转换为数组:String [] arr = list.toArray(new String [list.size()]);将数组作为第二个参数传递。

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

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

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

private ArrayList getFilteredUsers(String filter, ArrayList users) {

ArrayList 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.

*/

}

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

List name_list = new ArrayList<>();

name_list.add("A");

name_list.add("B");

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

List name_lowercase_list = new ArrayList<>();

for(int i =0 ; i

name_lowercase_list.add(name_list.get(i).toLowerCase().toString());

}

for(int i =0 ; 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 list = Arrays.asList("XYZ","ABC");

String matchingText ="XYZ1";

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

System.out.println(isMatched);

第二路

List list1= Arrays.asList("XYZ","ABC");

String searchStr ="abC";

boolean containsSearchStr = list1.stream().filter(searchStr::equalsIgnoreCase).findFirst().isPresent();

System.out.println(containsSearchStr);

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

List myList = new ArrayList(); //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 copyList = new ArrayList();

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),您应该能够执行想要的操作!

可以在调用ArrayList.contains()时指定此比较吗?

@AaronJLang我认为您无法做到这一点,因此它不是真正的解决方案。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值