我有一个名为FactorHelper
的Objective-C类,其定义如下。它有一个名为因子的属性,NSMutableArray
为NSNumbers
。我在这个类中有一个自定义isEqual:
方法,如果两个FactorHelper
对象中的因子属性具有相同的数字(即使数字的顺序不同),则返回true。
我尝试通过创建两个FactorHelper
对象一个10,5,2 和另一个10,2,5 进行测试。然后我创建了一个NSMutableSet
,添加了firstObject,然后添加了第二个对象。我期待第二个对象不被添加,但我看到它被添加了。当我单步执行代码时,我发现addObject正在调用isEqual
并返回TRUE
。我做错了什么?
更新
将[NSMutableSet new]
更改为[NSMutableSet alloc] init]
会使事情按预期进行。
此外,更改全部为TRUE,FALSE为isEqual为YES,NO使其行为正确(即使我将其保持为[NSMutableSet new]
)。
我不知道发生了什么事。有人可以解释一下吗?!
课程定义
@interface FactorHelper: NSObject
@property NSMutableArray <NSNumber *> *factors;
-(BOOL) isEqual:(FactorHelper *)other;
-(instancetype) initWithFactors:(NSMutableArray *)factors;
-(NSString *) description;
@end
@implementation FactorHelper
- (instancetype) initWithFactors:(NSMutableArray *)factors
{
self = [super init];
if (self) {
_factors = factors;
}
return self;
}
-(BOOL) isEqual:(FactorHelper *)other
{
if ([self.factors count] != [other.factors count])
{
return FALSE;
}
else
{
NSMutableDictionary <NSNumber *, NSNumber *> *myHashTable = [[NSMutableDictionary alloc] init];
for (NSNumber *nextNumber in self.factors) {
if(myHashTable[nextNumber] == nil)
{
myHashTable[nextNumber] = @(1);
}
else
{
myHashTable[nextNumber] = @([myHashTable[nextNumber] integerValue]+1);
}
}
for (NSNumber *nextNumber in other.factors)
{
if(myHashTable[nextNumber] == nil)
{
return FALSE;
}
else
{
myHashTable[nextNumber] = @([myHashTable[nextNumber] integerValue] - 1);
if ([myHashTable[nextNumber] integerValue] == 0) {
[myHashTable removeObjectForKey:nextNumber];
}
}
}
if ([[myHashTable allKeys] count] == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
}
@end
单元测试代码
NSMutableSet *testSet = [NSMutableSet new];
FactorHelper *fact1 = [[FactorHelper alloc] initWithFactors:[@[@(10),@(5),@(2)] mutableCopy]];
FactorHelper *fact2 = [[FactorHelper alloc] initWithFactors:[@[@(10),@(2),@(5)] mutableCopy]];
[testSet addObject:fact1];
[testSet addObject:fact2];
NSLog(@"Are factors 1 and 2 the same: %d",[fact1 isEqual:fact2]);
答案 0 :(得分:2)
NSMutableSet
是基于哈希值的集合。您需要覆盖与hash
一致的元素类型的isEqual:
方法。
在你的情况下,像这样:
- (NSUInteger)hash {
NSCountedSet *factorCounts = [[NSCountedSet alloc] initWithArray:self.factors];
return [@"FactorHelper" hash] + [factorCounts hash];
}
我不确定您是否检查了我是否看到它已添加,但这会使FactorHelper
与NSMutableSet
一起使用。
顺便说一下,使用isEqual:
可以缩短您的NSCountedSet
。
-(BOOL) isEqual:(FactorHelper *)other {
NSCountedSet *myFactorCounts = [[NSCountedSet alloc] initWithArray:self.factors];
NSCountedSet *otherFactorCounts = [[NSCountedSet alloc] initWithArray:other.factors];
return [myFactorCounts isEqual:otherFactorCounts];
}
这表明与上面的hash
更加清晰。
答案 1 :(得分:1)
你的代码从不正在工作,即使它有时会出现。
问题是isEqual
的自定义实现不是使类在Set中工作的唯一要求。想一想: 是什么?它是哈希表。因此,您还必须提供匹配的hash
自定义实现 - 您还没有这样做。
对可持续性的要求是:如果这两个对象相等,则两个对象的哈希值必须相同。