动态数组

数组是一种顺序存储的线性表,所有元素的内存地址是连续的。

接口设计

◼ int size(); // 元素的数量
◼ boolean isEmpty(); // 是否为空
◼ boolean contains(E element); // 是否包含某个元素
◼ void add(E element); // 添加元素到最后面
◼ E get(int index); // 返回index位置对应的元素
◼ E set(int index, E element); // 设置index位置的元素
◼ void add(int index, E element); // 往index位置添加元素
◼ E remove(int index); // 删除index位置对应的元素
◼ int indexOf(E element); // 查看元素的位置
◼ void clear(); // 清除所有元素

java实现

public class ArrayList <E> {

    //用来记录存入元素的数量
    private int size;
    //用来存放元素的数组
    private E elements[];
    //默认容量为10
    private static final int DEFAULT_CAPACITY = 10;

    //没有找到的标识
    public static final int ELEMENT_NOT_FOUND = -1;

    /**
     * @param capaticy 数组的容量,如果小于默认容量,则使用默认容量
     *
     */
    public ArrayList(int capaticy) {
        //如果容量小于默认容量,则使用默认容量
        capaticy = capaticy < DEFAULT_CAPACITY ? DEFAULT_CAPACITY:capaticy;
        elements = (E[]) new Object[capaticy];
    }

    /*
     * 无参构造函数,默认容量为 DEFAULT_CAPACITY
     * */
    public ArrayList() {
        this(DEFAULT_CAPACITY);
    }

    /*
    * @description 向数组最后面添加元素
    * @param element 要添加的元素
    * */
    public void add(E element) {
        //向数组最后添加元素,就是像数组index=size添加
        add(size,element);
    }

    /*
    * @description 向数组index的位置,添加元素element
    * @param index
    * @param element
    * */
    public void add(int index,E element) {
        //先检查index是否合法
        checkRangeForAdd(index);
        //再要确保elements的容量有size + 1;
        ensureCapaticy(size + 1);
        //将elements中 [index,size-1]区间内的元素依次向后移一个位置,从最后开始移
        for (int i = size; i > index; i--) {
            elements[i] = elements[i - 1];
        }
        //将element插入到index位置
        elements[index] = element;
        size++;
    }

    /*
    * @description 移除index处的元素
    * */
    public E remove(int index) {
        //首先检查index是否合法
        checkRange(index);
        //先获取index的元素,以便最后返回
        E oldElement = elements[index];
        //将[index+1,size-1]区间的元素依次向前移动一个。
        for (int i = index; i < size - 1; i++) {
            elements[index] = elements[index + 1];
        }
        //更新size
        size--;
        return oldElement;
    }

    /*
    * @description 清空数组中所有元素
    * */
    public void clear() {
        //遍历elements,置为null
        for (int i = 0; i < size - 1; i++) {
            elements[i] = null;
        }
        size = 0;
    }

    public E set(int index, E element) {
        //首先检查index是否合法
        checkRange(index);
        //合法的话,先获取index的旧元素以便最后返回
        E oldElement = elements[index];
        //替换新元素
        elements[index] = element;
        return oldElement;
    }

    /*
    * 获取动态数组中元素的数量
    * */
    public int size() {
        return size;
    }

    /*
    * 判断该数组是不是为空
    * */
    public boolean isEmpty() {
        return size == 0;
    }

    /*
    * @description 判断该数组是否包含元素 element,遍历判断
    * @param element 要比对的元素
    * */
    public boolean contains(E element) {
        return indexOf(element) != ELEMENT_NOT_FOUND;
    }

    /*
    * @description 根据元素返回该元素的下标
    * @param
    * */
    public int indexOf(E element) {
        //首先判断element是否为null
        if (element == null) {
            //遍历数组,找到就返回下标i
            for (int i = 0; i < size; i++) {
                if (elements[i] == null) return i;
            }
        } else {
            //遍历数组,找到就返回下标i
            for (int i = 0; i < size; i++) {
                if (element.equals(elements[i])) return i;
            }
        }
        //如果上面都没找到,返回 ELEMENT_NOT_FOUND
        return ELEMENT_NOT_FOUND;
    }

    /**
     * @description 根据角标获取元素
     * @param index 要查询的角标
     */
    public E get(int index) {
        //首先检查角标是否越界
        checkRange(index);
        return elements[index];
    }

    /*
    * @description 检查index是否合法
    * */
    private void checkRange(int index) {
        if (index > size - 1 || index < 0) {
            throw new ArrayIndexOutOfBoundsException("index: "+ index +"越界,Size=" + size);
        }
    }

    /*
     * @description 对Add操作检查index是否合法,判断的依据为index是否大于0,是否不超过size。
     * */
    private void checkRangeForAdd(int index) {
        if (index < 0 || index > size) {
            throw new ArrayIndexOutOfBoundsException("index: "+ index +"越界,Size=" + size);
        }
    }

    /*
     * @description 确保element有capaticy的容量,如果不够,则进行扩容
     * */
    private void ensureCapaticy(int capaticy) {
        //如果elements长度大于等于capaticy, do nothing
        if (elements.length >= capaticy) return;
        // 如果不够,先创建一个容量为elements 1.5倍的新数组,使用位运算效率要高。
        E[] newElements = (E[]) new Object[elements.length + (elements.length >> 1)];
        // 再将旧元素从elements中已入newElements中
        for (int i = 0; i < elements.length; i++) {
            newElements[i] = elements[i];
        }
        // 用newElements替代elements
        elements = newElements;
    }

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("size:" + size).append(",[");
        for (int i = 0; i < size; i++) {
            E element = elements[i];
            if (i != 0) stringBuilder.append(",");
            stringBuilder.append(element.toString());
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}

OC实现

GLArrayList.h

@interface GLArrayList <ObjectType> : NSObject

#pragma mark - 初始化
- (instancetype) init;
- (instancetype) initWithCapaticy:(int)capaticy;
+ (instancetype) new __unavailable;

#pragma mark - 增
- (void) addElement:(ObjectType)element;
- (void) addElement:(ObjectType)element atIndex:(int)index;

#pragma mark - 删
- (ObjectType) removeAtIndex:(int)index;
- (void) clear;

#pragma mark - 改
- (ObjectType) setElement:(ObjectType)element atIndex:(int)index;

#pragma mark - 查
- (int) size;
- (BOOL) isEmpty;
- (BOOL) containsElement:(ObjectType)element;
- (ObjectType) getElementAtIndex:(int)index;
- (int) indexOfElement:(ObjectType)element;

@end

GLArrayList.m

// 数组默认容量
static int const GL_ARRAY_LIST_DEFAULT_CAPATICY = 2;
static int const GL_ARRAY_LIST_NOT_FOUND = -1;
typedef void * AnyObject;

@interface GLArrayList()
{
    //用来存放元素的数组
    AnyObject *_array;
    //用来记录_array中元素的数量
    int _size;
    //用来记录_array中的容量
    int _capacity;
}
@end

GLArrayList.m

@implementation GLArrayList
#pragma mark - 初始化
- (instancetype) init {
    if (self = [super init]) {
        _array = calloc(GL_ARRAY_LIST_DEFAULT_CAPATICY, sizeof(AnyObject));
        _size = 0;
        _capacity = GL_ARRAY_LIST_DEFAULT_CAPATICY;
    }
    return self;
}
- (instancetype) initWithCapaticy:(int)capaticy {
    if (self = [super init]) {
        _array = calloc(capaticy, sizeof(AnyObject));
        _size = 0;
        _capacity = capaticy;
    }
    return self;
}


#pragma mark - 增

/// 将元素添加至数组最后
/// @param element 要添加的元素
- (void) addElement:(id)element {
    [self addElement:element atIndex:_size];
}
- (void) addElement:(id)element atIndex:(int)index {
    //先确定index是否合法
    if (index < 0 || index > _size) {
        @throw [GLArrayIndexOutOfBoundsException exeptionWithIndex:index];
    }
    //首先确保有size + 1 的容量,如果没有要扩容
    [self ensureCapaticy:_size + 1];
    // 把[index,size - 1]区间内从后开始,依次向后挪动一个单位
    for (int i = _size; i > index; i--) {
        _array[i] = _array[i - 1];
    }
    //将element插入index处
    _array[index] = (__bridge_retained AnyObject)element;
    _size++;
}


/// 确保_array有Capaticy的容量
/// @param capaticy 容量
- (void) ensureCapaticy:(int)capaticy {
    //如果当前容量大于capaticy, do nothing
    if (_capacity >= capaticy) return;
    //否则进行扩容,创建一个新数组,扩容为当前容量的1.5倍
    int newCapaticy = _capacity + (_capacity >> 1);
    GLLog(@"capaticy:%d -> %d",_capacity,newCapaticy);
    AnyObject *newArray = calloc(newCapaticy, sizeof(AnyObject));
    //将所有元素移入新数组中
    AnyObject *oldArray = _array;
    for (int i = 0; i < _size; i++) {
        newArray[i] = oldArray[i];
    }
    _array = newArray;
    _capacity = newCapaticy;
    free(oldArray);
}

#pragma mark - 删
- (id) removeAtIndex:(int)index {
    //首先检查index是否合法
    if (index < 0 || index > _size - 1) {
        @throw [GLArrayIndexOutOfBoundsException exeptionWithIndex:index];
    }
    //取出要移除的元素
    AnyObject elementToRemove = _array[index];
    //将[index+1,size -1]区间内的元素,从前到后依次向前移动一个单位
    for (int i = index; i < _size - 1; i++) {
        _array[i] = _array[i + 1];
    }
    _size--;
    GLLog(@"will remove %@",elementToRemove);
    return (__bridge_transfer id)elementToRemove;
}
- (void) clear {
    //遍历释放元素
    for (int i = 0; i < _size; i++) {
        CFRelease(_array[i]);
    }
    _size = 0;
}

#pragma mark - 改
- (id) setElement:(id)element atIndex:(int)index {
    //先检查index是否合法
    if (index < 0 || index > _size - 1) {
        @throw [GLArrayIndexOutOfBoundsException exeptionWithIndex:index];
    }
    //取出最后的元素以便返回
    AnyObject oldElement = _array[index];
    //将element覆盖index的位置
    _array[index] = (__bridge_retained AnyObject) element;
    CFRelease(oldElement);
    return (__bridge id)oldElement;
}

#pragma mark - 查
/// 获取当前数组中元素的数量
- (int) size {
    return self->_size;
}
/// 数组是否为空
- (BOOL) isEmpty {
    return self->_size == 0;
}
/// 数组中是否包含element元素
/// @param element 要对比的元素
- (BOOL) containsElement:(id)element {
    //遍历元素
    for (int i = 0; i < _size; i++) {
        if ([element isEqual:(__bridge id)(_array[i])]) return YES;
    }
    return YES;
}
/// 获取下标为index的元素
/// @param index 下标
- (id) getElementAtIndex:(int)index {
    //首先检查index是否合法
    if (index < 0 || index > _size - 1) {
        @throw [GLArrayIndexOutOfBoundsException exeptionWithIndex:index];
    }
    return (__bridge id)_array[index];
}

/// 获取element对应的下标
/// @param element element
- (int) indexOfElement:(id)element {
    for (int i = 0; i < _size; i++) {
        if ([element isEqual:(__bridge  id)_array[i]]) return i;
    }
    return GL_ARRAY_LIST_NOT_FOUND;
}

#pragma mark -

- (NSString *)description {
    NSMutableString *des = [NSMutableString string];
    [des appendFormat:@"size=%d,[",_size];
    for (int i = 0; i < _size; i++) {
        if (i != 0) {
            [des appendString:@","];
        }
        [des appendFormat:@"%@",_array[i]];
    }
    [des appendString:@"]"];
    return des;
}

- (void)dealloc
{
    [self clear];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容