当前位置: 首页 > 知识库问答 >
问题:

如何从集合接口中的容器方法在java中工作?

长孙瑞
2023-03-14

如果我从集合界面有两个对象列表

列表1={约翰,蒂姆,汤姆}

列表2={约翰,蒂姆}

这两个列表都是ArrayList的实例

Java怎么知道list2是否包含在list1中,list1.containsall(list2)?
我知道Java使用包含方法内部实现的容器()方法,和包含方法使用相等()方法。我理解差异,但我不确定Java如何遍历列表1的元素。

如果我使用列表1。containsAll(list2),constainsAll()方法是通过循环实现的,该循环遍历list2的每个对象,如果其中一个元素不在列表1中,则抛出false。

所以我的主要问题是JAVA如何知道列表1包含所有元素,而没有另一个循环来遍历列表1的元素?java是在内部工作还是什么?

我现在知道要做这样的事情,我必须使用

for(int i=0; i

清单1.get(i)。constainsAll(列表2);

,考虑到我必须修改containsAll的代码才能正确工作,并实现get()方法,这对我来说似乎更符合逻辑

共有1个答案

秦宏盛
2023-03-14

也许正式回答这个问题,因为我认为这是一个好问题。

containsAll方法遍历提供的集合,并对每个条目执行contains()方法,该方法还遍历正在比较的其他列表。请参阅下面的java代码摘录

  public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }

public boolean contains(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    return true;
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }

这使得这个o(n^2)(如果最后的值不匹配或列表实际匹配,则为最坏情况)(这真的很糟糕,尤其是当您正在比较大的集合时)。

更好的方法是执行以下操作:(显然,如果您使用除字符串之外的对象或其他集合并进行一些空检查或其他操作,则需要进行调整)

 public boolean containsAllStrings(List<String> list1, List<String> List2) {
        Map<String, String> list1Map = list1.stream().collect(Collectors.toMap(c -> c, c -> c));
        return List2.stream().allMatch(list1Map::containsKey);
    }

这样,它迭代的最大次数为2n(一个用于向地图添加项目,一个用于比较)次(n是2个列表中最大的一个),而不是n^2。

这看起来可能是一样的,但是哈希映射很好,因为它们包含一个指向内存中值的指针(使用键的哈希值),并且不会遍历所有值,使得访问映射中的值总是o(1)。这是最佳的。

显然,内存利用率等方法之间存在权衡,但就速度而言,这是最好的方法。

 类似资料:
  • 最近我正在学习Java8个特性,所以我从lambda表达式开始,然后我遇到了Java流API,现在我正在尝试围绕流API中的方法,它们是如何工作的? 我对lambda表达式的理解是,如果我们想将lambda表达式传递给该方法,那么我们需要使用单个未实现的方法(Java 8接口可以有默认实现)创建一个与lambda表达式的签名匹配的接口。然后,传递lambda表达式的方法可以通过调用接口方法来执行l

  • 问题内容: 我创建了一个简单的演示: 问题在于的一部分根本没有运行。 如果我只使用两个参数并且等于provider ,它将运行。 如何使方法工作? 问题答案: 首先,由于没有要合并的内容,因此不需要在非并行流中执行合并器。 其次,您的问题源于使用和。应该使用累加器通过将第二个参数与第一个参数结合来修改第一个参数,但是由于Java中的字符串是不可变的,因此您的代码不会产生任何结果。 将创建一个新字符

  • 我最近开始在一个项目中使用MapStruct映射工具。过去,为了映射DTO->实体,反之亦然,我使用自定义映射器,例如: 在尝试获取一个可选对象时,我可以通过以下方式将实体映射到dto: 目前,正如我之前提到的,我使用的是mapStruct,问题是我的映射器是这样的,而不是类,它是这样的接口: 我想知道是否可以在stream gentle中使用这个接口方法来映射我的值,而不需要包装值,比如: 谢谢

  • 如果我使用,但和两个参数等于supplier,它就会运行。 如何使在方法中工作?

  • 在我的Java(Spring Boot)应用程序中,我有以下服务接口: 并将以下服务方法作为实现: 现在我需要实现一个类似的服务,它将使用ProductService而不是BrandService: 如果我使用这种方法,我无法从Controller调用正确的实现,如下所示: 在这个场景中,我应该如何正确地合并这两个服务?我认为可能需要创建2个继承自PDFService的接口,但不确定是否有更好的方

  • 虽然我对Java不是很陌生,但以下问题让我非常困惑,以至于我无法克服。我在网上搜索了很多,也找到了一些答案,但并不完全令人满意。谁能帮我消除疑虑吗 我的困惑是: 问题1:迭代器是一个接口,我们不能实例化或创建接口的对象。那么,我们应该在这里称之为“iter”,它是什么? 问题1.1:迭代器的所有方法(例如next())都由“iter”调用。这些方法在哪里定义?如果这些方法是在向量类的特定内部类中定