为什么在Kotlin中仅使用[列表,地图,集合]集合?

时间:2019-07-14 10:44:32

标签: kotlin collections

我一直在学习Kotlin,并且遇到了Collections API。在Kotlin之前,我一直在学习Java,并且我知道Java中有很多不同类型的Collections API。例如,我们使用List, Map, Queue, Set等代替常规ArrayList, HashMap, LinkedList, LinkedMap。尽管在Kotlin中,我们仅使用常规类型,例如Map, List, Set,但也可以使用HashMap等。因此,那里发生了什么事?你能帮我弄清楚吗?

1 个答案:

答案 0 :(得分:4)

虽然Kotlin最初的主要目标是JVM,但JetBrains大力推动使其成为multiplatform,并同时支持JS和Native。

如果您在JVM上使用Kotlin,则您使用的任何集合的实现仍将是原始JDK类,例如java.util.ArrayListjava.util.HashSet。 Kotlin标准库没有重新实现这些功能,它具有很多优点:

  • 这些都是经过测试的实现,无论如何都可以维护。
  • 使用完全相同的类使与Java互操作变得轻而易举,因为您可以来回传递它们而不必执行任何类型的转换或映射。

Kotlin所做的是在这些现有实现的基础上引入它们自己的集合语义,它们以标准库接口的形式出现,例如ListMap,{{1 }},MutableList等。只需compiler magic的一小部分,现有的JDK类也可以实现这些接口。


如果您不需要特定类型的集合的特定实现,则可以通过这些接口以及标准库的相应工厂方法(MutableMaplistOf,{ {1}},mapOf等)。这使您的代码更加通用,并且独立于具体的基础实现。您不知道标准库mutableListOf函数将为您创建哪个特定类,只是它将是满足mutableMapOf接口协定的对象。

您基本上应该在代码中默认使用这些接口,尤其是在公共API中:

  • 对于函数参数,这使客户端可以向函数提供他们希望提供给您的集合的任何实现。如果您的函数可以在mutableListOf上执行任何操作,则应仅请求该接口-没有理由专门要求MutableListList
  • 如果这是返回类型,则使用这些接口可以使您更改将来在内部创建的特定实现,而不会破坏客户端代码。您可以保证只返回ArrayList的东西,而支持该列表的实现不会向您的客户公开。

如果您查看Kotlin标准库的所有collection handling functions,您会发现从表面上看,它们几乎完全在这些接口上运行。如果深入研究,您会发现正在创建LinkedList个实例,但这不会暴露给客户端代码,因为它通常不必关心具体的实现。


再次回到多平台点,如果您以仅依赖Kotlin标准库定义的类型的方式编写代码,则该代码将很容易用于非JVM目标。如果在导入中引用MutableList,则可以立即编译为JS代码,因为每个平台上都有该接口的Kotlin标准库实现。无论是直接映射到现有类,以某种方式包装现有类,还是从头开始为Kotlin实施,都不必担心。但是,如果您在代码中引用ArrayList,那将无法实现JS目标,因为那里没有Java平台类。


您是否仍可以直接使用诸如kotlin.MutableList之类的类?当然可以。

  • 如果您有时看不到代码跨平台运行,那么直接使用Java集合是完全可以的。
  • 如果出于性能原因而需要java.util.TreeSetjava.util.ArrayList的特定实现,则有时必须直接使用Java类。

有趣的是,在Kotlin的最新版本中,这些特定类型的实现(例如,基于数组的列表)也包装在标准库类型别名下,因此默认情况下它们与平台无关:请参见kotlin.collections.ArrayList或{ {3}}例如。这些Kotlin定义的类型通常会在IntelliJ完成中首先出现,因此您会发现自己被迫尽可能使用它们。对于大多数例外情况也是如此,例如kotlin.collections.HashSet


TL; DR:您可以在Kotlin中使用Java类型的Kotlin集合类型,但是您应该尽可能地使用Java类型。