iOS 데이터 구조의 배열 조작 방법
본 고 는 학습 태도 에 따라 NSArray 와 NSMutableArray 를 모방 하여 하나의 배열 유형 을 실현 하기 로 결정 했다.물론 성능 은 NSArray 와 NSMutableArray 가 좋 지 않 을 수도 있 고 100000 만 개의 데 이 터 를 삽입 할 수도 있다.시간 적 으로 NSMutableArray 의 세 배 정도 이다.물론 평소에 사용 한 과정 에서 100000 번 의 이런 큰 데 이 터 를 배열 에 추가 하 는 경 우 는 드 물 기 때문에 성능 은 무시 할 수 있다.
Array List.h 주요 방법 은 NSArray 와 NSMutableArray 를 그대로 옮 기 는 방법 이름 을 설명 합 니 다.
테스트 결과 먼저 보 내 주세요.
dispatch_async(dispatch_get_global_queue(0, 0), ^{
Person *p1 = [[Person alloc] init];
NSMutableArray *array = [NSMutableArray arrayWithCapacity:100000];
// ArrayList
*array = [ArrayList arrayWithCapacity:100000];
CFAbsoluteTime startTime =CFAbsoluteTimeGetCurrent();
for (int i = 0; i<100000; i++) {
[array addObject:p1];
}
CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
CFTimeInterval duration = linkTime * 1000.0f;
NSLog(@"Linked in %f ms",duration);
[self->_timeArray addObject:@(duration)];
count++;
});
NSMutableArray 5.081740292635832 ms
ArrayList 16.27591523257168 ms
ArrayList , C
//
// ArrayList.m
// ArrayList
//
// Created by dzb on 2018/7/19.
// Copyright © 2018 . All rights reserved.
//
#import "ArrayList.h"
static NSInteger const defaultCapacity = 10;
typedef void * AnyObject;
@interface ArrayList ()
{
AnyObject *_array;
NSInteger _size;
NSInteger _capacity;
}
@end
@implementation ArrayList
#pragma mark - init
- (instancetype)init
{
self = [super init];
if (self) {
[self resetArray];
}
return self;
}
+ (instancetype)array {
return [[ArrayList alloc] initWithCapacity:defaultCapacity];
}
+ (instancetype)arrayWithCapacity:(NSUInteger)numItems {
return [[ArrayList alloc] initWithCapacity:numItems];
}
- (instancetype)initWithCapacity:(NSUInteger)numItems {
_capacity = numItems;
_array = calloc(_capacity,sizeof(AnyObject));
_size = 0;
return self;
}
/**
*/
- (void) resetArray {
_size = 0;
if (_array != NULL)
_array[_size] = NULL;
free(_array);
_capacity = defaultCapacity;
_array = calloc(_capacity, sizeof(AnyObject));
}
#pragma makr -
- (void)addObject:(id)anObject {
[self insertObject:anObject atIndex:_size];
}
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index {
if (!anObject) {
@throw [NSException exceptionWithName:@"add object null." reason:@"object must be not null ." userInfo:nil];
return;
}
///
if ((index > _size)) {
@throw [NSException exceptionWithName:@"Array is out of bounds" reason:@"out of bounds" userInfo:nil];
return;
}
if (_size == _capacity-1) { ///
[self resize:2*_capacity];
}
///
if (self.count > 0 ) {
for(NSInteger i = _size - 1 ; i >= index ; i--)
_array[i + 1] = _array[i];
}
self->_array[index] = (__bridge_retained AnyObject)(anObject);
_size++;
}
#pragma mark -
- (void)removeAllObjects {
NSInteger i = _size-1;
while (_size > 0) {
[self removeObjectAtIndex:i];
i--;
}
[self resetArray];
}
- (void)removeObjectAtIndex:(NSUInteger)index {
///
if ((index > _size)) {
@throw [NSException exceptionWithName:@"Array is out of bounds" reason:@"out of bounds" userInfo:nil];
return;
}
AnyObject object =(_array[index]);
CFRelease(object);
for(NSInteger i = index + 1 ; i < _size ; i ++)
_array[i - 1] = _array[i];
_size--;
_array[_size] = NULL;
///
if (_size == _capacity/2) {
[self resize:_capacity/2];
}
}
- (void)removeObject:(id)anObject {
NSInteger index = [self indexOfObject:anObject];
if (index == NSNotFound) return;
[self removeObjectAtIndex:index];
}
- (void)removeLastObject {
if ([self isEmpty]) return;
[self removeObjectAtIndex:_size-1];
}
#pragma mark -
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {
if (!anObject) {
@throw [NSException exceptionWithName:@"add object null." reason:@"object must be not null ." userInfo:nil];
return;
}
///
if ((index > _size)) {
@throw [NSException exceptionWithName:@"Array is out of bounds" reason:@"out of bounds" userInfo:nil];
return;
}
_array[index] = (__bridge AnyObject)(anObject);
}
#pragma mark -
- (BOOL) isEmpty {
return (self->_size == 0);
}
- (BOOL) isFull {
return (self->_size == self->_capacity-1);
}
- (id)objectAtIndex:(NSUInteger)index {
if ((index > _size)) {
@throw [NSException exceptionWithName:@"Array is out of bounds" reason:@"out of bounds" userInfo:nil];
return nil;
}
if ([self isEmpty]) { return nil; }
AnyObject obj = _array[index];
if (obj == NULL) return nil;
return (__bridge id)(obj);
}
- (NSUInteger)indexOfObject:(id)anObject {
for (int i = 0; i<_size; i++) {
id obj = (__bridge id)(_array[i]);
if ([anObject isEqual:obj]) return i;
}
return NSNotFound;
}
- (BOOL)containsObject:(id)anObject {
for (int i = 0; i<_size; i++) {
id obj = (__bridge id)(_array[i]);
if ([anObject isEqual:obj]) return YES;
}
return NO;
}
- (id)firstObject {
if ([self isEmpty]) return nil;
return (__bridge id _Nullable)(_array[0]);
}
- (id)lastObject {
if ([self isEmpty]) return nil;
return (__bridge id _Nullable)(_array[_size]);
}
- (NSUInteger)count {
return _size;
}
- (NSString *)description {
NSMutableString *string = [NSMutableString stringWithFormat:@"
ArrayList %p : [
" ,self];
for (int i = 0; i<_size; i++) {
AnyObject obj = _array[i];
[string appendFormat:@"%@",(__bridge id)obj];
if (i<_size-1) {
[string appendString:@" ,
"];
}
}
[string appendString:@"
]
"];
return string;
}
/**
@param capacity
*/
- (void) resize:(NSInteger)capacity {
AnyObject *oldArray = _array;
AnyObject *newArray = calloc(capacity, sizeof(AnyObject));
for (int i = 0 ; i<_size; i++) {
newArray[i] = oldArray[i];
}
_array = newArray;
_capacity = capacity;
free(oldArray);
}
- (void)dealloc
{
if (_array != NULL)
[self removeAllObjects];
free(_array);
// NSLog(@"ArrayList dealloc");
}
@end
테스트 를 통 해 배열 내부 에 저 장 된 대상 에 대해 retain 작업 을 할 것 입 니 다.인용 계수+1 은 대상 이 배열 에서 제거 할 때 대상 의 메모리 인용 계수-1 을 정상적으로 사용 할 수 있 기 때문에 대상 의 메모리 관리 문 제 를 걱정 하지 않 아 도 됩 니 다.배열 의 기본 길 이 는 10 입 니 다.개발 자가 배열 의 길 이 를 확정 하지 않 을 때 그 내 부 는 동적 으로 확장 하여 배열 의 길 이 를 늘 릴 수 있 습 니 다.reove 작업 을 수행 할 때 도 배열 내부 길 이 를 줄 입 니 다.NSArray 와 NSMutableArray 등 상용 API 를 구현 하 였 으 며,성능 에 특별히 신경 쓰 는 장면 이 아니라면 Array List 를 사용 하여 데 이 터 를 저장 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Swift의 패스트 패스Objective-C를 대체하기 위해 만들어졌지만 Xcode는 Objective-C 런타임 라이브러리를 사용하기 때문에 Swift와 함께 C, C++ 및 Objective-C를 컴파일할 수 있습니다. Xcode는 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.