Java 在Arraylist中查找多个对象的有效方法

Java 在Arraylist中查找多个对象的有效方法,java,string,arraylist,equals,contains,Java,String,Arraylist,Equals,Contains,我必须检查arraylist是否包含通过对象传递的任何值 考虑一个值为“abc”、“jkl”、“def”、“ghi”的数组列表。 和String check=“abc,ghi” 我们必须检查字符串中的任何值(abc或ghi)是否存在于arraylist中,并且我们可以在找到匹配项时停止检查 传统上,我们可以使用逗号拆分字符串检查,并在迭代中为每个逗号分隔的值使用arraylist.contains() 但这很耗时。有没有更好的方法来执行此检查。您可以将检查转换为regexp,并在数组列表中循环一

我必须检查arraylist是否包含通过对象传递的任何值

考虑一个值为“abc”、“jkl”、“def”、“ghi”的数组列表。 和
String check=“abc,ghi”

我们必须检查字符串中的任何值(abc或ghi)是否存在于arraylist中,并且我们可以在找到匹配项时停止检查

传统上,我们可以使用逗号拆分
字符串检查
,并在迭代中为每个逗号分隔的值使用
arraylist.contains()


但这很耗时。有没有更好的方法来执行此检查。

您可以将
检查
转换为regexp,并在
数组列表中循环一次

String check = "abc,ghi";
Pattern p = Pattern.compile("(" + check.replace(',', '|') + ")");
List<String> list = Arrays.asList(new String[] { "abc", "jkl", "def", "ghi" });
for (String element : list) {
    if (p.matcher(element).matches()) {
        System.out.println("match: " + element);
    }
}
String check=“abc,ghi”;
模式p=Pattern.compile(“(“+check.replace(”,“,“|”)+”);
List List=Arrays.asList(新字符串[]{“abc”、“jkl”、“def”、“ghi”});
for(字符串元素:列表){
if(p.matcher(element.matches()){
System.out.println(“匹配:+元素);
}
}

一种方法是使用
retainAll
方法和
Set
s

示例

// note an additional "ghi" here
List<String> original = new ArrayList<String>(Arrays.asList(new String[]{"abc", "jkl","def", "ghi", "ghi"}));
Set<String> clone = new HashSet<String>(original);
Set<String> control = new HashSet<String>(Arrays.asList(new String[]{"abc","ghi"}));
clone.retainAll(control);
System.out.println(clone.equals(control));
这仍然是O(n),但您可以从搜索字符串构建一个集合,然后只需在列表上迭代一次:

HashSet<String> checks = new HashSet<String>();
checks.addAll(Arrays.asList(check.split(",")));
for (String item : arraylist) {
    if (checks.contains(item)) {
        // Found one
    }
}
HashSet checks=newhashset();
checks.addAll(Arrays.asList(check.split(“,”));
for(字符串项:arraylist){
如果(检查。包含(项目)){
//找到一个
}
}

ArrayList的最佳搜索时间是O(n),除非对其进行排序,在这种情况下,您将得到O(lgn)。是否可以使用
HashMap
TreeMap
?请注意,如果输入是ArrayList,则对其进行排序需要O(n log n),将条目放入HashMap或HashSet需要O(n)。你也必须考虑到这一点——你不能只说HashMap查找是O(1)并完成它。@user3580294是的,这就是为什么我写了“如果输入是ArrayList”。顺便说一句,在这种情况下,集合比映射更合适。映射用于将键映射到值;集合用于询问值是否存在,这是此处需要的。您不需要使用
HashMap
进行迭代,但是,是的,这就是查找键的方式。正如@yshavit所指出的,你必须小心——如果你只是为了这个而切换集合,你很可能会受到超过你可能获得的任何好处的惩罚。@yshavit是的,完全没有做到这一点。。。我需要新眼镜。是的,
Set
可能会更好,但如果将
Set
用于这种特定情况,仍然会受到复制惩罚(尽管是较小的惩罚),由于附加的限制,
集合
通常不能替代
ArrayList
。这是ArrayList的最佳方式吗?@Beauflitz很难说什么是“最佳”。我想这会掩盖您所做的额外循环,但我不知道
是如何匹配的()
方法有效,我无法告诉您此循环相对于原始循环的性能特征。有点吹毛求疵:当您在
clone
上调用
retainal
时,您实际上使用的是
Set#retainal
而不是
List#retainal
@Beauflitz,我可以这么说,虽然有很多因素需要考虑。有一点是肯定的,将
集合
s表示为
字符串
s以比较或操纵它们绝对不是推荐的做法。@blalasaadri刚刚看到您的评论-谢谢(删去了模棱两可的部分)。根据讨论,避免了arraylist和set之间的切换,数据可以直接存储在set中,无需克隆。现在,我们有'retainAll()'和'equals()',两个操作需要时间,对吗?我们可以用一个步骤解决问题吗?因为,当在
Set clone
中找到
Set control
中的一个对象时,我们可以停止搜索。“abc”或“ghi”。不需要在父集合中同时存在这两个属性。那么,我们如何才能使这个解决方案更好呢?根据讨论,
Set
优于
Arraylist
。因此,如果数据在
Hashset
中也可用,我们是否可以使用equals/contains方法来查找检查中的任何一个字符串是否存在于项中?有一些有效的方法可以判断两个集合是否具有相同的值。但是在您的问题中,您有两个列表——arraylist和
split
输出。您必须迭代列表才能将其转换为集合。将两个列表转换为集合只是为了进行集合交集,这项工作比必要的工作要多。输入数据可以直接存储在
hashset
中,而不是存储在
arraylist
中。因此,现在它是一个数据的
哈希集
,搜索值出现在一个
字符串中
由逗号分隔。比如,
String check=“abc,ghi”
HashSet<String> checks = new HashSet<String>();
checks.addAll(Arrays.asList(check.split(",")));
for (String item : arraylist) {
    if (checks.contains(item)) {
        // Found one
    }
}