swift中NSMutableDictionary.lazy的含义是什么?

时间:2017-03-01 05:27:54

标签: objective-c swift nsmutabledictionary lazy-sequences

我对使用 lazy 功能的位置感到困惑,我的意思是说我应该在集合中使用 lazy 关键字来处理哪种类型的条件。

3 个答案:

答案 0 :(得分:1)

延迟评估是指延迟表达式的评估,直到需要结果为止。这与渴望评估相反,后者是对表达式的评估立即进行的。

考虑这个表达式:

let input = [1, 2, 3]
let evens = input.map{ $0 * 2 }

闭包{ $0 * 2 }将每个数字(1,2,3)映射到一个新值,将它们乘以2.这个评估是急切的。也就是说,执行此行的时刻是执行map函数的评估,并且计算结果存储在evens中。 input的类型为Array<Int>,结果evens的类型为Array<Int>

现在考虑一下这个表达式:

let input = [1, 2, 3]
let evens = input.lazy.map{ $0 * 2 }

闭包{ $0 * 2 }的每个数字(1,2,3)一个新值,它们将它们乘以2.但是,这个评估是懒惰的。也就是说,在执行此行时,不会进行乘法运算。而是存储闭包{ $0 * 2 }以供将来参考。 input的类型为Array<Int>,结果evens的类型为LazyMapRandomAccessCollection<Array<Int>, Int>。乘法推迟到元素访问。如果永远不会访问某个元素,那么它永远不会被处理。

在这种微不足道的情况下,存储关闭以供将来评估的簿记开销将大于仅仅急切地计算结果。但是,您可以设想这样的情况:

let input = 1...1000000000
let evens = input.lazy.map{ $0 * 2 }
print(evens[0])

在序列中的所有1000000000中,只有一个被使用过。评估闭包1000000000次,产生1000000000结果,将它们全部存储在内存中是非常低效的,如果只需要第一个元素。

lazySequence协议的实例方法。所有符合类型的类型,包括NSMutableDictionary都会实现它。它们都做同样的事情:它们推迟处理mapfilter语句中的元素,直到需要它们的结果为止。在有许多元素的情况下,这可以节省内存和处理时间,并且只需要一小部分元素。

答案 1 :(得分:1)

来自Apple Docs:

  

惰性存储属性是一个属性,其初始值在第一次使用之前不会计算。通过在声明之前编写惰性修饰符来指示延迟存储的属性。

使用@lazy属性时,请记住以下内容:

  • 懒惰属性必须始终使用var关键字声明,而不是使用let常量声明。
  • 延迟属性在声明时必须初始化。

我们如何在Objective-C中实现延迟功能

@property (nonatomic, strong) NSMutableArray *players;

- (NSMutableArray *)players 
{
    if (!_players) {
        _players = [[NSMutableArray alloc] init];
    }
    return _players;
}

现在在Swift中,您可以使用lazy属性实现相同的功能。见下面的例子

class Person {

    var name: String

    lazy var personalizedGreeting: String = {

        return "Hello, \(self.name)!"
    }()

    init(name: String) {
        self.name = name
    }
}

现在,当您初始化某个人时,尚未创建他们的个人问候语:

let person = Person(name: "John Doe")  // person.personalizedGreeting is nil

但是当您尝试打印个性化问候语时,它会即时计算:

print(person.personalizedGreeting)
// personalizedGreeting is calculated when used
// and now contains the value "Hello, John Doe!"

我希望这有助于您了解懒惰属性的功能。

答案 2 :(得分:0)

延迟工作的方式是初始化程序(或init方法)仅在首次访问变量或属性时运行。我看到在你的代码中它不能工作(至少是直接)的一个主要原因,那是因为你将两个惰性实例化代码打包到一个方法中(loadEntriesIfNeeded)。

要使用延迟实例化,您可能需要扩展NSMutableArray和NSDictionary,并为您的延迟实例化覆盖或创建自定义初始化程序。然后,将loadEntriesIfNeeded中的代码分发到各自的初始值设定项中。

import Swift

println("begin")

class ClassWithLazyProperties {

    lazy var entries:[String] = ClassWithLazyProperties.loadStuff()
    lazy var entriesByNumber:Dictionary<Int, String> = {

        var d = Dictionary<Int, String>()
        for i in 0..<self.entries.count {
            d[i] = self.entries[i]
        }
        return d
    }()

    private class func loadStuff() -> [String] {
        return ["Acai", "Apples", "Apricots", "Avocado", "Ackee", "Bananas", "Bilberries"]
    }

}

let c = ClassWithLazyProperties()
c.entriesByNumber
    // 0: "Acai", 1: "Apples", 2: "Apricots", 3: "Avocado", 4: "Ackee", 5: "Bananas", 6: "Bilberries"]


println("end")