【问题标题】:Time Complexity of Realm Lists in SwiftSwift 中领域列表的时间复杂度
【发布时间】:2020-12-21 17:58:41
【问题描述】:

我想知道领域列表是如何快速实现的。更具体地说,我想知道它们是链接列表还是它们的工作方式类似于数组列表。例如,在索引处检索项目的时间复杂度是多少。假设我有一个长度为 m 的领域列表 A,我想检索 A[n],这个操作会像链接列表一样在 O(n) 中运行,还是像在数组列表中一样在 O(k) 中运行。

编辑:

以下是对问题的进一步澄清:

假设我想将用户的好友列表存储在 Realm 数据库中。我这样做的方法是定义一个新的类用户,如下所示:

Class User: Object{
    @objc dynamic var name: String?
    @objc dynamic var userName: String?
    @objc dynamic var email: String?
    var friendList = RealmSwift.List<String>() //Contains the names of all friends
}

假设我已将一些朋友添加到用户的朋友列表中,并且我想在我的应用程序中的其他位置访问此朋友列表并显示特定的朋友:

var realm = try! Realm()
var user = realm.objects(User.self)[0]
var friendToDisplay = user.friendList[4]
print(friendToDisplay)

我想知道user.friendList[4] 操作的时间复杂度是多少。如果 Realm 将 RealmSwift.List 视为链表,那么复杂度必须是 O(n),而如果当用户被调用到内存时,RealmSwift.List 被实现为 ArrayList 然后访问列表中的第四个内存地址将是 O(1)。

我的好奇心来自于想知道哪个会更快:

  1. 遍历列表并找到我们想要显示的朋友的名字:
var realm = try! Realm()
var user = realm.objects(User.self)[0]
var friendName = "Peter"
for friend in user.friendList{
    if friend == friendName {
        print(friend)
    }
}

  1. 知道我们要显示的朋友的索引,比如说索引 4:
var realm = try! Realm()
var user = realm.objects(User.self)[0]
var friendToDisplay = user.friendList[4]
print(friendToDisplay)

在这两种情况下,假设朋友的姓名或我们正在使用的索引存在于朋友列表中。

【问题讨论】:

  • 这将是非常主观的并且是特定于用例的,因为 Realm 对象是延迟加载的,而不是像传统的 Array 或 Linked List 实现那样“保存在内存中”。您能否提供一个示例用例并澄清问题?
  • 您好@Jay 感谢您的回复,很抱歉我的问题不够清楚。我添加了一个示例以使其更清晰。

标签: swift realm realm-list


【解决方案1】:

由于涉及的变量数量和 Realm 的固有性质,这个问题无法直接回答。我将提供一些信息,但让我澄清一点很重要。

Realm 不支持 Lists 中的原语(非常好)。

编辑: 10.7 版增加了对过滤器/查询以及基元聚合函数的支持,因此以下信息不再完全有效。但是,这仍然需要注意。

所以你不会想要这样做

var friendList = RealmSwift.List<String>()

但是,您需要定义一个 FriendClass 来保存有关您朋友的详细信息

class FriendClass: Object {
   @objc dynamic var friendName = ""
}

然后这样做

let friendList = List<FriendClass>()

现在回答你的问题:

您的问题是关于通过遍历列表知道索引来寻找朋友。虽然您可以以编程方式进行,但两者都不是理想的解决方案。

如果你想为你的朋友 Peter 找到你的 FriendClass 对象,这是最快的方法

if let peter = realm.objects(FriendClass.self).filter("friendName == 'Peter'").first {
   //do something with the peter object
}

请记住,它正在与领域中的所有朋友对象一起工作。您也可以在特定列表上执行相同的操作。所以如果你的用户对象有一个friendsList列表:

if let peter = user.friendsList.filter("friendName == 'Peter'").first {
   //do something with the peter object
}

这是变量位:Realm 对象是延迟加载的。这允许 Realm 包含数百万个对象,但在需要它们之前不会将它们加载到内存中。这样可以防止设备不堪重负。

这是一个巨大的变量,因为磁盘访问和对象是否已加载可能会产生影响。但是,使用我上面介绍的技术,无论是朋友列表中的 1 个还是 10,000 个朋友,查询几乎都是即时的。

我们的一个项目有 10GB 的数据,上面显示的过滤器会立即对这些数据做出来自 Realm 的响应。

现在是其他变量:

  1. 主键

如果您的对象有主键,您可以直接读取该对象而不会弄乱

let peter = realm.object(ofType: FriendClass.self, forPrimaryKey: "peters key")

为了清楚起见,具有主键的对象需要 O(log n) 时间。 n 是数据库中该类型对象的数量。简而言之,检索朋友所需的时间与 Realm 中的对象总数无关。

  1. 索引

索引对象使写入速度稍慢,但查询速度更快,在上面的示例中,如果将 name 设置为 indexedProperty,则在查询该属性时会提高整体读取速度

  1. 列表

如果间接,列表是另一层,一般来说,它比直接读取对象“慢”。话虽如此,“较慢”是高度主观的,并且与用例相关。花 0.03 秒从 100,000 人的列表中检索朋友并没有什么影响。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-15
    • 2017-01-13
    • 1970-01-01
    • 2012-09-25
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多