0

我有一个名为 Objective-C 的类FactorHelper,其定义如下。它有一个称为因子的属性,它是 的NSMutableArray一个NSNumbers。我isEqual:在这个类中有一个自定义方法,如果两个FactorHelper对象中的因子属性具有相同的数字(即使数字的顺序不同),它返回 true。

我试图通过创建两个FactorHelper对象来进行测试,一个是 10,5,2另一个是 10,2,5。然后我创建了一个NSMutableSet,添加了 firstObject,然后添加了第二个对象。我期待第二个对象不会被添加,但我看到它被添加了。当我单步执行代码时,我发现isEqualaddObject 正在调用它并返回TRUE. 我究竟做错了什么?

更新

更改[NSMutableSet new]to[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]);
4

2 回答 2

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上述更清晰的一致性。

于 2016-07-30T21:23:49.920 回答
1

你的代码从来没有工作过,即使有时看起来是这样。

问题是自定义实现isEqual并不是使类在 Set 中工作的唯一要求。想一想:什么集合?它是一个哈希表。所以你还必须提供一个匹配的自定义实现hash——你还没有这样做。

哈希性的要求是:如果两个对象相等,则两个对象的哈希值必须相同。

于 2016-07-30T21:23:12.097 回答