iOS 데이터 구조의 배열 조작 방법

배열 은 선형 구 조 는 용기 유형 으로 연속 적 인 메모리 공간 입 니 다.iOS 에 서 는 NSArray 와 NSMutableArray 집합 형식 으로 대상 유형 을 저장 합 니 다.그 중에서 NSArray 는 가 변 형식 이 고 NSMutableArray 는 가 변 형식 으로 배열 의 요 소 를 추가 삭제 하고 검사 할 수 있 습 니 다.
본 고 는 학습 태도 에 따라 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 를 사용 하여 데 이 터 를 저장 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기