前言:在此之前,我们封装的数组属于静态数组,也即数组空间固定长度,对于固定长度的数组当元素超过容量时会报数组空间不足。为了能更好的使用数组,我们来实现一个可以自动扩充容量的数组。
实现思路:
1.当数组容量达到事先定义值时创建一个空间是data数组两倍的newData数组(扩容);
2.把data数组中的元素全部赋值到newData数组中;
3.把data数组重新执行newData数组。
一、定义核心扩容方法
// 数组扩容
private void resize(int newCapacity){
E[] newData = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
newData[i] = data[i];
}
data = newData;
}
二、改进之前的数组添加元素方法(数组空间不够时自动扩容 --原理空间的2倍)
//在第index个位置插入一个新元素
public void add(int index, E e) {
//(1)判断当前需要插入值的位置是否合理,合理则转入(3),否则抛出位置不合法异常
if (index < 0 || index > size)
throw new IllegalArgumentException("您选择的位置不合法");
//(2)先判断当前数组容量是否已满,满则进行容量扩充
if (size == data.length)
resize(data.length * 2);
//将index位置之后的元素往后依次移动一位
for (int i = size - 1; i >= index; i--) {
//(3)将index之后的元素依次往后移动一位,然后将新元素插入到index位置
data[i + 1] = data[i];
}
data[index] = e;
//(4)维护size值
size++;
}
三、改进之前的数组删除元素方法(数组空间空闲太大就会缩容(原来空间的1/2))
//从数组中删除index位置的元素,返回删除的元素
public E remove(int index) {
//1.判断索引的选择是否合法
if (index < 0 || index > size)
throw new IllegalArgumentException("您选择的位置不合法");
//2.先存储需要删除的索引对应的值
E ret = data[index];
//将索引为index之后(index)的元素依次向前移动
for (int i = index + 1; i < size; i++) {
//3.执行删除--实质为索引为index之后(index)的元素依次向前移动,将元素覆盖
data[i - 1] = data[i];
}
//4.维护size变量
size--;
// loitering objects != memory leak 手动释放内存空间
data[size] = null;
if (size == data.length / 2) {
resize(data.length / 2);
}
//5.返回被删除的元素
return ret;
}
通过以上,我们就可以实现一个动态的数组。
测试一下改进后的代码:
1.测试addLast()
DynamicArray<Integer> arr=new DynamicArray<Integer>(10);
for (int i = 0; i < 10; i++) {
arr.addLast(i);
}
System.out.println("添加数组元素:");
System.out.println(arr);
结果为:
2.测试add(int index,E e)方法
arr.add(1, 100);
System.out.println("在数组指定索引位置插入元素e:");
System.out.println(arr);
结果:
现在数组已经从刚才定义的容量为10个变为了容量为20个,数组中元素为11个,为此实现了数组扩容。
3.测试removeLast方法
System.out.println("删除数组最后一个元素:");
arr.removeLast();
System.out.println(arr);
结果为:
此时我们可以看出,删除一个元素之后,数组容量又从新变为了10个。
此小节到此为止,若你喜欢,关注我,我们一起加油!
本节所有代码:
1 /**
2 * 3.动态数组
3 * 数组容量可变
4 */
5
6
7 public class DynamicArray<E> {
8 //使用private 的目的是防止用户从外界修改,造成数据不一致
9 private E[] data;
10 private int size;//数组中元素个数
11
12 //构造函数,传入数组的容量capacity构造Array函数
13 public DynamicArray(int capacity) {
14 data = (E[]) new Object[capacity];//泛型不能直接实例化
15 size = 0;
16 }
17
18 //无参构造函数,默认数组的容量capacity=10
19 public DynamicArray() {
20 this(10);
21 }
22
23 //获取数组中元素个数
24 public int getSize() {
25 return size;
26 }
27
28 //获取数组的容量
29 public int getCapacity() {
30 return data.length;
31 }
32
33 //获取数据是否为空
34 public boolean iEmpty() {
35 return size == 0;
36 }
37
38 //向所有元素后添加元素
39 public void addLast(E e) {
40 add(size, e);//size表示此时的最后一个元素
41 }
42
43 //在所有元素之前添加一个新元素
44 public void addFirst(E e) {
45 add(0, e);//0表示第一个位置
46 }
47
48 //在第index个位置插入一个新元素
49 public void add(int index, E e) {
50 //(1)判断当前需要插入值的位置是否合理,合理则转入(3),否则抛出位置不合法异常
51 if (index < 0 || index > size)
52 throw new IllegalArgumentException("您选择的位置不合法");
53
54 //(2)先判断当前数组容量是否已满,满则进行容量扩充
55 if (size == data.length)
56 resize(data.length * 2);
57
58
59 //将index位置之后的元素往后依次移动一位
60 for (int i = size - 1; i >= index; i--) {
61 //(3)将index之后的元素依次往后移动一位,然后将新元素插入到index位置
62 data[i + 1] = data[i];
63 }
64 data[index] = e;
65 //(4)维护size值
66 size++;
67 }
68
69 //获取index索引位置的元素
70 public E get(int index) {
71 //(1)判断当前需要插入值的位置是否合理,合理则转入(2),否则抛出位置不合法异常
72 if (index < 0 || index > size)
73 throw new IllegalArgumentException("您选择的位置不合法");
74
75 //(2)返回索引index对应的值
76 return data[index];
77 }
78
79 //获取最后一个元素
80 public E getLast() {
81 return get(size - 1);
82 }
83
84 //获取第一个元素
85 public E getFirst() {
86 return get(0);
87 }
88
89 //修改index索引位置的元素为e
90 void set(int index, E e) {
91 //(1)判断当前需要插入值的位置是否合理,合理则转入(2),否则抛出位置不合法异常
92 if (index < 0 || index > size)
93 throw new IllegalArgumentException("您选择的位置不合法");
94
95 //(2)修改索引index对应的值
96 data[index] = e;
97 }
98
99 //查找数组中是否包含元素e
100 public boolean contains(E e) {
101 for (int i = 0; i < size; i++) {
102 if (data[i] == e)
103 return true;
104 }
105 return false;
106 }
107
108 //查找数组中元素e所在的索引(只是一个),如果不存在元素e,则返回-1;
109 public int find(E e) {
110 for (int i = 0; i < size; i++) {
111 if (data[i] == e)
112 return i;
113 }
114 return -1;
115 }
116
117 //从数组中删除index位置的元素,返回删除的元素
118 public E remove(int index) {
119 //1.判断索引的选择是否合法
120 if (index < 0 || index > size)
121 throw new IllegalArgumentException("您选择的位置不合法");
122
123 //2.先存储需要删除的索引对应的值
124 E ret = data[index];
125
126 //将索引为index之后(index)的元素依次向前移动
127 for (int i = index + 1; i < size; i++) {
128 //3.执行删除--实质为索引为index之后(index)的元素依次向前移动,将元素覆盖
129 data[i - 1] = data[i];
130 }
131 //4.维护size变量
132 size--;
133 // loitering objects != memory leak 手动释放内存空间
134 data[size] = null;
135
136 //缩容操作
137 if (size == data.length / 2 && data.length != 0) {
138 resize(data.length / 4);
139 }
140 //5.返回被删除的元素
141 return ret;
142 }
143
144 //从数组中删除第一个元素,返回删除的元素
145 public E removeFirst() {
146 return remove(0);
147 }
148
149 //从数组中删除最后一个元素,返回删除的元素
150 public E removeLast() {
151 return remove(size - 1);
152 }
153
154 //从数组中删除元素(只是删除一个)
155 public void removeElement(E e) {
156 int index = find(e);
157 if (index != -1)
158 remove(index);
159 }
160
161 // 数组扩容方法
162 private void resize(int newCapacity) {
163 E[] newData = (E[]) new Object[newCapacity];
164 for (int i = 0; i < size; i++) {
165 newData[i] = data[i];
166 }
167 data = newData;
168 }
169
170 @Override
171 public String toString() {
172 StringBuilder res = new StringBuilder();
173 res.append(String.format("Array:size=%d, capacity=%d\n", size, data.length));
174 res.append('[');
175 for (int i = 0; i < size; i++) {
176 res.append(data[i]);
177 if (i != size - 1) {
178 res.append(",");
179 }
180 }
181 res.append(']');
182 return res.toString();
183 }
184
185 }
测试代码:
1 public class test {
2 public static void main(String[] args) {
3
4 DynamicArray<Integer> arr=new DynamicArray<Integer>(10);
5 for (int i = 0; i < 10; i++) {
6
7 arr.addLast(i);
8 }
9 System.out.println("添加数组元素:");
10 System.out.println(arr);
11
12 arr.add(1, 100);
13 System.out.println("在数组指定索引位置插入元素e:");
14 System.out.println(arr);
15
16 System.out.println("删除数组最后一个元素:");
17 arr.removeLast();
18 System.out.println(arr);
19
20 }
21 }
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有