数组是一种顺序存储的线性表,所有元素的内存地址是连续的。
接口设计
◼ 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];
}