java由于jdk提供的数组是静态的
当数组被初始化后,该数组的长度就不可变了。java程序中的数组必须经过初始化才可以使用。所谓初始化,就是为数组对象的元素分配内存空间,并为每个数组元素指定初始值。
优缺点
1、静态数组:已经确定子数组大小的数组。会造成空间浪费。
2、动态数组:使用动态数组的优点是可以根据用户需要,有效利用存储空间。
不管什么方式,一旦初始化后,其长度就不可变,可以通过数组length属性(注意与length()的区别)来访问数组的长度。
动态实现
/**
* 动态数组
*/
public class Array<T> {
/**
* 数组
*/
private T[] data;
/**
* 数组个数 容量
*/
private int size;
/**
* 构造函数 用来进行初始数组 capacity 表示动态的初始数组大小
*
* @param capacity
*/
public Array(int capacity) {
//由于历史java不支持T进行new 需要大类Object强制为T
data = (T[]) new Object[capacity];
size = 0;
}
/**
* 无参构造 默认的大小
*/
public Array() {
this(10);
}
/**
* 获取元素个数
*/
public int getSize() {
return this.size;
}
/**
* 获取容量
*
* @return
*/
public int getCatacity() {
return data.length;
}
/**
* 判断数组是否为null
*
* @return
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 每次相数组后面添加一个数 size 是当前数组的位置和个数 size++ 就是每次向后面添加一个数进行位置加1
*
* @param e
*/
public void addArray(T e) {
if (size == data.length) {
throw new IllegalArgumentException("超过了初始数组容量的限制");
} else {
data[size] = e;
size++;
}
}
/**
* 在 数组某个位置 添加元素,
*
* @param index 某个位置的索引
* @param e 数
*/
public void addIndexArray(int index, T e) {
if ( index > size && index < 0) {
throw new IllegalArgumentException("超过了初始数组容量的限制");
} else {
if(size == data.length){
//数组动态扩容 由于java是静态数组 要重新封装数组 扩容机制2陪根据数组本身大小来扩容
resize(2 * data.length);
}
//找的数组的前面的数进行 i-- 每找到一个数就i+1往后挪移 i> index 就是有多少就在前面找到多少
for (int i = size - 1; i >= index; i--) {
//如果没找到就把当前数往后移
data[i + 1] = data[i];
}
// 表示找到了那个索引进行添加
data[index] = e;
size++;
}
}
/**
* 删除指定元素
*
* @param index
* @return
*/
public T removeArray(int index) {
if (index <= 0 || index >= size) {
throw new IndexOutOfBoundsException("大了");
}
T datum = data[index];
//index +1 就是找到后一个元素data[i - 1] = data[i];表示找到的后一个元素往前移动,替换掉要删除的元素
for (int i = index + 1; i < size; i++) {
data[i - 1] = data[i];
}
//用泛型就变成存储的是类数据,但是删除数组某个数会有一个默认看不见的数,但是用了泛型类就被引用了就会一直存在,要进行回收,否则占内存
//Hang out Objects
data[size] = null;
size--;
//动态缩小容量 但是不能和扩容一样 否则造成每次删除数组都要缩小 避免复杂度震荡
if(size == data.length / 2) {
resize(data.length / 2);
}
return datum;
}
/**
* 删除头元素
*
* @return
*/
public T removeFirst() {
return this.removeArray(0);
}
/**
* 删除最后元素
*
* @return
*/
public T removeLast() {
return this.removeArray(size - 1);
}
/**
* 获取数组中的某个元素
*
* @param index
* @return
*/
public T get(int index) {
if (index <= 0 || index >= size) {
throw new IndexOutOfBoundsException("大了");
}
return data[index];
}
/**
* 根据索引修改替换当前的数
*
* @param index
* @param e
*/
public void set(int index, T e) {
if (index <= 0 || index >= size) {
throw new IndexOutOfBoundsException("大了");
}
data[index] = e;
}
/**
* 找数组中某个元素
*
* @param e
* @return
*/
public boolean contains(T e) {
for (int i = 0; i < size; i++) {
if (data[i].equals(e)) {
return true;
}
}
return false;
}
/**
* 找数组中某个元素索引
*
* @param e
* @return
*/
public int containsIndex(T e) {
for (int i = 0; i < size; i++) {
if (data[i].equals(e)) {
return i;
}
}
return -1;
}
@Override
public String toString() {
return super.toString();
}
public static void main(String[] args) {
Array array = new Array(10);
for (int i = 0; i < 10; i++) {
array.data[i] = i;
}
array.removeArray(7);
}
/**
* 动态扩容
* @param kuoron
*/
private void resize(int kuoron){
//新数组
T[] t = (T[])new Object[kuoron];
//循环原来的容量移动到新的数组里面
for (int i = 0; i < size; i++) {
//原来的容量移动到新的数组里面
t[i] = data[i];
}
//然后赋值 使原来的引用指向现状新数组
data = t;
}
}