学习资源:慕课网liyubobobo老师的《玩儿转数据结构》
目录
1、简介
- 把数据码成一排进行存放

- 存储的数据类型相同
- 每一个数据在数组中对应一个索引,索引从0开始;索引可以有语意,也可以没有语意
- 数组初始化后大小就固定了;添加、删除元素都受限
1.1、静态数组初始化
//方式一
int[] arr1 = new int[10];
//方式二
int[] arr2 = new int[]{0,1,2,3};
//方式三
int arr3 = {0,1,2,3,4,5,6,7,8,9}
1.2、数组的遍历(迭代)
for(int i = 0; i< arr.length; i++){
arr[i]
}
for(数据类型 temp : arr){
temp
}
1.3、数组元素的的修改
arr[i] = newValue
1.4、数组最大的优点
- 存储有序,可遍历,方便快速查询
- 数组最好应用于“索引有语意"的情况
- 支持随机访问
2、动态数组(抽象)接口
public interface Array<E> {
void insert(int index, E element);
void remove(int index);
void set(int index);
void get(int index);
}
3、动态数组的实现
3.1、实现原理
- 内部封装一个静态数组
- 对外提供增删改查等,静态数组所没有的方法
3.2、使用泛型
-
让我们的数据结构可以放置“任何”数据类型
-
泛型不可以是基本数据类型,只能是类对象
boolean,byte , char , short,int , long , float , double
-
每个基本数据类型都有对应的包装类
Boolean,Int,Float,Double,Byte,Char,Short,Long ,
-
如果类为泛型类,但是在创建对象时,可以不使用泛型这个选项。
Java中创建泛型数组
//不支持
T[] array = new T[n];
//必须写为
T[] array = (T[])new Object[n];
3.3、动态化
-
添加元素时满足某一条件,自动扩容
-
删除元素时满足某一条件,自动缩容
3.4、代码
public class Array<E> {
private E[] data;
private int size;
//有参构造器
public Array(int capacity) {
data = (E[]) new Object[capacity];
size = 0;
}
//无参构造器
public Array() {
this(10);
}
public Array(E[] arr) {
data = (E[]) new Object[arr.length];
for (int i = 0; i < arr.length; i++) {
data[i] = arr[i];
}
size = arr.length;
}
//获取数组容量
public int getCapacity() {
return data.length;
}
//获取数组大小
public int getSize() {
return size;
}
//判断数组是否已满
public boolean isFull() {
return getSize() == getCapacity();
}
//判断数组是否位空
public boolean isEmpty() {
return getSize() == 0;
}
//判断是否包含某元素
public boolean ifContains(E element) {
for (int i = 0; i < size; i++) {
if (data[i].equals(element)) {
return true;
}
}
return false;
}
//获取某元素的索引,只能找到第一个
public int getIndex(E element) {
for (int i = 0; i < size; i++) {
if (data[i].equals(element)) {
return i;
}
}
return -1;
}
//扩容操作,内部执行
private void resize(int newCapacity) {
E[] newData = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
newData[i] = data[i];
}
data = newData;
}
//头部插入一个元素
public void insertToHead(E element) {
insert(0, element);
}
//尾部插入一个元素
public void insertToLast(E element) {
insert(size, element);
}
//插入一个元素,插入位置:数组头、尾、元素之间
public void insert(int index, E element) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("插入索引不正确");
}
//数组扩容
if (isFull()) {
resize(2 * getCapacity());
}
for (int i = size - 1; i >= index; i--) {
data[i + 1] = data[i];
}
data[index] = element;
size++;
}
//删除头
public E removeHead() {
return remove(0);
}
//删除头
public E removeLast() {
return remove(size - 1);
}
//指定下标删除一个元素,并返回该元素
public E remove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("删除失败,索引超出数组合法界限");
}
E result = data[index];
for (int i = index; i < size - 1; i++) {
data[i] = data[i + 1];
}
size--;
data[size] = null;//手动删除引用
if (size == getCapacity() / 4 && data.length / 2 != 0) {
resize(getCapacity() / 2);
}
return result;
}
//删除指定元素,只能删除第一个
public boolean removeElement(E element) {
int index = getIndex(element);
if (getIndex(element) != -1) {
remove(index);
return true;
}
return false;
}
//修改一个元素
public void set(int index, E newValue) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("修改失败,索引超出数组合法界限");
}
data[index] = newValue;
}
//获取一个元素,空着的位置不可以获取值
public E get(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("获取失败,索引超出数组合法界限");
}
return data[index];
}
//获取头元素
public E getHead() {
return get(0);
}
//获取尾元素
public E getLast() {
return get(size - 1);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(String.format("Array:size=%d, capacity=%d
", size, data.length));
builder.append("[");
for (int i = 0; i < size; i++) {
builder.append(data[i]);
if (i != size - 1) {
builder.append(", ");
}
}
builder.append("]");
return builder.toString();
}
//交换两个索引处的值
public void swap(int i, int j) {
if (i < 0 || i >= size || j < 0 || j >= size)
throw new IllegalArgumentException("索引越界");
E e = data[i];
data[i] = data[j];
data[j] = e;
}
}
3.5、测试
public class Test {
public static void main(String[] args) {
Array<Integer> intArray = new Array<>();
System.out.println("是不是空数组"+intArray.isEmpty());
intArray.addToHead(10);
intArray.addToHead(20);
intArray.addToLast(15);
intArray.add(1, 39);
System.out.println("是不是空数组"+intArray.isEmpty());
System.out.println("是否包含15:"+intArray.ifContains(15));
System.out.println(intArray.getSize());
System.out.println(intArray.getCapacity());
System.out.println(intArray);
System.out.println("最后一个整数是:"+intArray.getLast());
System.out.println("第一个整数是:"+intArray.getHead());
System.out.println("索引为2的整数是"+intArray.get(2));
intArray.removeLast();
intArray.removeHead();
intArray.remove(1);
System.out.println(intArray);
System.out.println("是否包含15:"+intArray.ifContains(15));
}
}
4、Java中的动态数组
java.util.ArrayList
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
}
API接口
