集合中的可变对象 [英] Mutable Objects in Collections

查看:95
本文介绍了集合中的可变对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘自文档, 将可变对象存储在集合对象中可能会导致问题.如果某些集合包含的对象发生突变,则某些集合可能变得无效,甚至损坏,因为通过突变,这些对象会影响它们在集合中的放置方式.首先,如果更改后的属性会影响对象的哈希或isEqual:方法的结果,则作为哈希集合中键的对象的属性(例如NSDictionary对象或NSSet对象)将被破坏. (如果集合中对象的哈希方法不依赖于它们的内部状态,则损坏的可能性较小.)其次,如果有序集合中的对象(例如排序数组)的属性发生了变化,则这可能会影响对象的方式与数组中的其他对象进行比较,从而使排序无效.

From the docs, Storing mutable objects in collection objects can cause problems. Certain collections can become invalid or even corrupt if objects they contain mutate because, by mutating, these objects can affect the way they are placed in the collection. First, the properties of objects that are keys in hashing collections such as NSDictionary objects or NSSet objects will, if changed, corrupt the collection if the changed properties affect the results of the object’s hash or isEqual: methods. (If the hash method of the objects in the collection does not depend on their internal state, corruption is less likely.) Second, if an object in an ordered collection such as a sorted array has its properties changed, this might affect how the object compares to other objects in the array, thus rendering the ordering invalid.

但是当我记录结果时,该对象会完美地添加到集合中.其实这样做是不安全的?

But when I logs the results, the object is added to the collection perfectly. Actually doing this is not safe??

-(void)mutableObjectsinCollections{
 NSMutableArray *arr1 = [[NSMutableArray alloc]init];
 NSMutableArray *arr2 = [[NSMutableArray alloc]init];
 NSMutableArray *arr3 = [[NSMutableArray alloc]init];
 NSMutableArray *arr4 = [[NSMutableArray alloc]init];


 [self addObjectsToArrayBefore:arr1];
 [self addObjectsToArrayBefore:arr2];
 [self addObjectsToArrayBefore:arr3];
 [self addObjectsToArrayBefore:arr4];

 NSDictionary *dict = @{@"arr1": arr1,@"arr2": arr2,@"arr3": arr3,@"arr4": arr4,@"arr5": arr5};
 NSLog(@"%@",dict);

 [self addObjectsToArrayAfter:arr1];
 [self addObjectsToArrayAfter:arr2];
 [self addObjectsToArrayAfter:arr3];
 [self addObjectsToArrayAfter:arr4];

 NSLog(@"%@",dict);
}

-(void)addObjectsToArrayBefore:(NSMutableArray *)arr{

for (int i = 1; i<10; i++) {
      [arr addObject:[NSNumber numberWithInteger:i]];
}
}

-(void)addObjectsToArrayAfter:(NSMutableArray *)arr{

for (int i = 10; i<20; i++) {
    [arr addObject:[NSNumber numberWithInteger:i]];
  }
}

推荐答案

我将向您展示一个示例.

I will show you an example.

让我们为字典定义我们自己的可变键,请注意它可以被复制,它定义了hash和相等性的实现.

Let's define our own mutable key for a dictionary, note it can be copied, it defines an implementation of hash and of equality.

@interface MyKey : NSObject <NSCopying>

@property (nonatomic, copy, readwrite) NSString *keyData;

@end

@implementation MyKey

- (id)initWithData:(NSString *)data {
    self = [super init];

    self.keyData = data;

    return self;
}

- (id)copyWithZone:(NSZone *)zone {
    MyKey *key = (MyKey *) [[[self class] alloc] init];
    key.keyData = self.keyData;

    return key;
}

- (NSUInteger)hash {
    return self.keyData.length;
}

- (BOOL)isEqual:(id)object {
    if (![object isMemberOfClass:[self class]]) {
        return NO;
    }

    MyKey *key = object;

    return [self.keyData isEqualToString:key.keyData];
}

@end

现在让我们有一个简单的测试用例:

Now let's have a simple test case:

让我们定义一些键

MyKey *key1 = [[MyKey alloc] initWithData:@"key1"];
MyKey *key2 = [[MyKey alloc] initWithData:@"key2"];
MyKey *keyX = [[MyKey alloc] initWithData:@"XXX"];

还有一个简单的字典

NSDictionary *dictionary = @{key1: @"value1", key2: @"value2"};

让我们看看里面有什么

NSLog(@"%lu", (unsigned long) dictionary.count);
NSLog(@"%@", dictionary);
NSLog(@"%@", [dictionary objectForKey:key1]);
NSLog(@"%@", [dictionary objectForKey:key2]);
NSLog(@"%@", [dictionary objectForKey:keyX]);

给予(预期)

2
{
    "<MyKey: 0x10010a8d0>" = value1;
    "<MyKey: 0x100108e40>" = value2;
}
value1
value2
(null)

现在让我们更改键的值

[(MyKey *)[[dictionary allKeys] objectAtIndex:0] setKeyData:@"XXX"];

让我们再次看看里面是什么

Let's see what's inside again

NSLog(@"%lu", (unsigned long) dictionary.count);
NSLog(@"%@", dictionary);
NSLog(@"%@", [dictionary objectForKey:key1]);
NSLog(@"%@", [dictionary objectForKey:key2]);
NSLog(@"%@", [dictionary objectForKey:keyX]);

给予

2   //expected
{
    "<MyKey: 0x10010a8d0>" = (null);  //huh, null value?
    "<MyKey: 0x100108e40>" = value2;
}
(null) //huh?
value2
(null) //huh?

出了什么问题?

使用哈希表实现字典的内部结构.它们的hash键用于搜索值.一旦我们更改了密钥中的数据,哈希值也将更改.结果,字典将无法找到为给定键存储的值.

The internal structures of a dictionary are implemented using a hash table. The hash of they key is used to search a value. Once we change the data in the key, the hash value will also change. As a result, the dictionary won't be able to find the value stored for the given key.

这篇关于集合中的可变对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆