【问题标题】:The best way to check if List<String[]> contains a String[] [duplicate]检查 List<String[]> 是否包含 String[] 的最佳方法 [重复]
【发布时间】:2014-10-14 17:18:21
【问题描述】:

我有一个List 声明为:

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

这个List 包含多个Strings 数组。

我需要检查我拥有的String[] 是否包含在此ArrayList&lt;String[]&gt; 中。

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

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

有没有更好的方法来检查ArrayList&lt;String[]&gt; 是否包含特定的String[]

【问题讨论】:

  • 看起来不错。当前方法有什么问题?
  • arrayList.contains(myStringArray)
  • @bigdestroyer 这不起作用。
  • 我同意@sᴜʀᴇsʜᴀᴛᴛᴀ - 你的效率不能比O(n*n) 更好(等于n BTW)
  • if(!Arrays.equals()) 你真的想否定等于吗?

标签: java arrays string collections


【解决方案1】:

Array.equals() 是最有效的方法afaik。该方法仅用于此目的,并且优化得尽可能少,因为它在实现中的current state 是单个for 循环。

去吧。

【讨论】:

  • 在我看来这不是回应,它不会为当前帖子增加任何价值。如果您将其添加为问题的评论就足够了...
  • @user503413 -1 ??当 OP 要求最好的方法时,我只是说当前的方法是最好的方法。这就像一个是/或问题。
【解决方案2】:

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

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

这为您提供了有用的 hashCodeequals 方法,允许您使用 ArrayList.contains,或者如果包含测试是主要关注点,甚至可以使用 HashSets:

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 有可能比您现在的要快得多正在做。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 这是真的,因为您将相同的引用传递给添加的 String 数组。尝试创建一个与array 相同内容的新数组
    • 是的,并且传递具有相同元素的另一个数组实例将返回false(但也应该返回true)!
    • 建议改进。
    【解决方案4】:

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

    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 取决于 OP 的需求。他说他有一个列表,所以也许他需要按索引获取元素。仅当数组从未被修改时,缓存哈希码才会起作用。
    猜你喜欢
    • 2022-01-09
    • 2011-03-19
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    • 2017-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多