List<String[]>包含一个String[]的最佳检查方法

8

我有一个声明为 List 的列表:

List<String[]> arrayList = new ArrayList<>();

这个List包含多个String数组。

我需要检查一个String[]是否包含在这个ArrayList<String[]>中。

我目前正在遍历这个ArrayList并将每个String[]与我要搜索的那个进行比较:

for(String[] array: arrayList){
    if(Arrays.equals(array, myStringArray)){
        return true;
    }
}
return false;

有没有更好的方法来检查一个 ArrayList<String[]> 是否包含特定的 String[]


5
看起来还不错。目前的方法有什么问题吗? - Suresh Atta
2
@bigdestroyer 这个不起作用。 - Swadeesh
3
if(!Arrays.equals()) 你真的想要否定equals吗? - icza
1
我需要检查 [...] 是否存在 - 这正是上帝赐予我们哈希集的原因。 - Chris Martin
1
@BoristheSpider /同意!将[]与泛型混合使用,特别是[]与列表混合使用,在大约95%的情况下都是一个糟糕的想法(请参见Bloch EJ 2nd中的原理和示例)- 要么保持[][](在Java中比在C中更容易使用),要么使用List<List<>>/Set<List<>>;我认为这个问题比OP认为的更深刻 - 他的问题不是来自(有争议的)API知识的缺乏,而是来自于使用错误的抽象。 - user719662
显示剩余10条评论
4个回答

9

Array.equals() 是我所知道的最有效的方法。该方法专门用于此目的,并在实现的当前状态中进行了优化,仅使用了一个for循环。

只需去做吧。


在我看来,这不是一个回复,它没有为当前的帖子增加任何价值。如果你把它作为评论添加到问题中就足够了... - Olimpiu POP
5
当OP问最好的方法时,我只是在告诉他现在的方法是最好的方法。这就像一个是/否问题。 - Suresh Atta

6

我同意Rod_Algonquin的答案, 但还有另一种方法。只需编写自己的类,包装数组并实现自定义equals和hashCode方法,并让它们返回Arrays.equals()和Arrays.hashCode()。使用此方法,您可以将对象存储在List中,并直接对列表进行包含检查。

List<ArrayWrapper> list = new ArrayList<ArrayWrapper>();
list.add(new ArrayWrapper(new String[]{"test", "123"}));
list.add(new ArrayWrapper(new String[]{"abc", "def"}));
list.add(new ArrayWrapper(new String[]{"789", "cgf"}));

String[] arrayToSearchFor = {"test", "123"};
ArrayWrapper wrapperToSearchFor = new ArrayWrapper(arrayToSearchFor);
System.out.println(list.contains(wrapperToSearchFor));

String[] arrayToSearchFor2 = {"hello", "123"};
ArrayWrapper wrapperToSearchFor2 = new ArrayWrapper(arrayToSearchFor2);
System.out.println(list.contains(wrapperToSearchFor2));


class ArrayWrapper
{
    private String[] array;

    public ArrayWrapper(String[] array)
    {
        this.array = array;
    }

    public String[] getArray()
    {
        return array;
    }

    @Override
    public int hashCode()
    {
        return Arrays.hashCode(array);
    }

    @Override
    public boolean equals(Object obj)
    {
        if (!(obj instanceof ArrayWrapper))
        {
            return false;
        }

        return Arrays.equals(array, ((ArrayWrapper) obj).getArray());
    }
}

这将会被打印出来

true
false

好主意,但如果您使用Set而不是List,并让ArrayWrapper缓存其hashCode,那不是更好吗? - Yogu
@Yogu 取决于 OP 的需求。他说他有一个列表,所以也许他需要按索引获取元素。如果数组从未被修改,缓存哈希码才能起作用。 - CalibeR.50

1

我可能会寻找一种解决方案,不直接将String[]对象存储在列表中。这可能意味着创建某种有意义的类来在内部存储String[],或者只是切换到ArrayList而不是数组。但是,如果不知道上下文,我最好的建议是使用Arrays.asList将它们包装成列表。

// Make a List that uses the provided array for its contents:
List<String> stringList = Arrays.asList(stringArray);

这将为您提供有用的hashCodeequals方法,使您能够使用ArrayList.contains,甚至是HashSet,如果包含测试是主要关注点:
Set<List<String>> stringLists = new HashSet<>();

// when you want to add a String[]:
stringLists.add(Arrays.asList(stringArray));

// when you want to check whether a String[] is in the set:
stringLists.contains(Arrays.asList(stringArray));

ArrayList.contains 不会比你目前做的更快,所有的 Arrays.asList 调用很可能会很啰嗦,但是 HashSet.contains 有潜力比你目前做的要快得多。


1

List.contains(Object) 在处理数组列表时存在问题,为什么不使用嵌套列表呢?

您可以使用 Arrays.asList(T... a) 轻松将数组转换为列表。

String[] array = new String[2];
array[0] = "item1";
array[1] = "item2";
List<List<String>> arrayList = new ArrayList<List<String>>();
arrayList.add(Arrays.asList(array));

1
这是正确的,因为您将添加的 String 数组的相同引用传递了进去。尝试创建一个具有与 array 相同内容的新数组。 - Rod_Algonquin
1
是的,传递另一个具有相同元素的数组实例将返回false(但也应返回true)! - icza
改进并附带建议。 - spongebob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接