java创建动态数组

简介: java创建动态数组

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

动态数组相对于一般数组的优势是可以灵活地添加或删除元素。而一般数组则受限于固定的内存空间。只能有限的添加元素

动态数组(Dynamic Array)接口设计

◼ 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(); // 清除所有元素

上代码:

动态数组类的实现:

public class ArrayList {
//动态数组至少应该有数组的长度和元素的索引两个成员变量。
/**
• 元素的数量
*/
private int size;
/**
• 所有的元素
*/
private E[] elements;
//在创建数组时要有一个初始的容量,容量的大小根据实际情况确定,避免重复申请或销毁内存。
private static final int DEFAULT_CAPACITY = 10;
//这里用来进行判定
private static final int ELEMENT_NOT_FOUND = -1;
public ArrayList(int capaticy) {
//如果实际需要的容量比默认容量小,就使用默认容量
capaticy = (capaticy < DEFAULT_CAPACITY) ? DEFAULT_CAPACITY : capaticy;
elements = (E[]) new Object[capaticy];
}
public ArrayList() {
this(DEFAULT_CAPACITY);
}
/**
• 清除所有元素
*/
public void clear() {
//为了使动态数组可以存储多种类型的元素使用了泛型
//这样的话new的数组里每个位置存储的是元素内存的索引
//这样清空的时候需要将每个内存的索引都必须清除
//否则内存中的元素依然可以被访问
for (int i = 0; i < size; i++) {
elements[i] = null;
}
//动态数组的使用过程中可能会反复的添加或删除元素,因此没有必要每次清空元素的时候都销毁数组所在的内存空间
//因为申请和销毁内存空间都是需要时间的
size = 0;
}
/**
• 元素的数量
• @return
*/
public int size() {
return size;
}
/**
• 是否为空
• @return
*/
public boolean isEmpty() {
return size == 0;
}
/**
• 是否包含某个元素
• @param element
• @return
*/
public boolean contains(E element) {
return indexOf(element) != ELEMENT_NOT_FOUND;
}
/**
• 添加元素到尾部
• @param element
*/
public void add(E element) {
add(size, element);
}
/**
• 获取index位置的元素
• @param index
• @return
*/
public E get(int index) {
rangeCheck(index);
return elements[index];
}
/**
• 设置index位置的元素
• @param index
• @param element
• @return 原来的元素ֵ
*/
public E set(int index, E element) {
rangeCheck(index);
E old = elements[index];
elements[index] = element;
return old;
}
/**
• 在index位置插入一个元素
• @param index
• @param element
*/
public void add(int index, E element) {
//加这一行不允许存空值
//if(element==null)return;
//在插入元素之前先要判断输入的索引位置
rangeCheckForAdd(index);
ensureCapacity(size + 1);
for (int i = size; i > index; i--) {
elements[i] = elements[i - 1];
}
elements[index] = element;
size++;
}
/**
• 删除index位置的元素
• @param index
• @return
*/
public E remove(int index) {
rangeCheck(index);
E old = elements[index];
//需要往前挪的元素是index后一个到数组的最后一个
for (int i = index + 1; i < size; i++) {
elements[i - 1] = elements[i];
}
//size-1,之后将末尾的元素清空
elements[--size] = null;
return old;
}
/**
• 查看元素的索引
• @param element
• @return
*/
public int indexOf(E element) {
if (element == null) { // 1
for (int i = 0; i < size; i++) {
if (elements[i] == null) return i;
}
} else {
for (int i = 0; i < size; i++) {
//判断相等的时候使用==是比较内存地址是否相等
if (element.equals(elements[i])) return i; // n
}
}
return ELEMENT_NOT_FOUND;
}
//public int indexOf2(E element) {
//for (int i = 0; i < size; i++) {
//if (valEquals(element, elements[i])) return i; // 2n
//}
//return ELEMENT_NOT_FOUND;
//}
//
//private boolean valEquals(Object v1, Object v2) {
//return v1 == null ? v2 == null : v1.equals(v2);
//}
/**
• 保证要有capacity的容量
• @param capacity
*/
private void ensureCapacity(int capacity) {
int oldCapacity = elements.length;
if (oldCapacity >= capacity) return;
// 新容量为旧容量的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
E[] newElements = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
newElements[i] = elements[i];
}
elements = newElements;
System.out.println(oldCapacity + "扩容为" + newCapacity);
}
private void outOfBounds(int index) {
throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
}
private void rangeCheck(int index) {
if (index < 0 || index >= size) {
outOfBounds(index);
}
}
private void rangeCheckForAdd(int index) {
//插入元素的时候可以大于数组的现有长度
if (index < 0 || index > size) {
outOfBounds(index);
}
}
@Override
public String toString() {
// size=3, [99, 88, 77]
StringBuilder string = new StringBuilder();
string.append("size=").append(size).append(", [");
for (int i = 0; i < size; i++) {
if (i != 0) {
string.append(", ");
}
string.append(elements[i]);
//if (i != size - 1) {
//string.append(", ");
//}
}
string.append("]");
return string.toString();
}
}
相关文章
|
7月前
|
存储 Java
Java动态数组实现----聊聊ArrayList
Java动态数组实现----聊聊ArrayList
77 2
|
7月前
|
存储 算法 Java
【数据结构与算法】1、学习动态数组数据结构(基本模拟实现 Java 的 ArrayList 实现增删改查)
【数据结构与算法】1、学习动态数组数据结构(基本模拟实现 Java 的 ArrayList 实现增删改查)
177 0
|
存储 安全 Java
【JavaSE专栏50】Java集合类Vector解析,一款线程安全的动态数组容器
【JavaSE专栏50】Java集合类Vector解析,一款线程安全的动态数组容器
|
存储 缓存 安全
【JavaSE专栏48】Java集合类ArrayList解析,这个动态数组数据结构你了解吗?
【JavaSE专栏48】Java集合类ArrayList解析,这个动态数组数据结构你了解吗?
|
存储 Java 索引
深入探究Java ArrayList:动态数组的优雅实现
在Java编程世界中,ArrayList是一种常用且灵活的数据结构,它能够在数组的基础上提供更多的功能和便利。本文将带您深入了解Java中的ArrayList,包括其特点、用法、性能以及实际应用场景。
|
存储 Java 编译器
这些编程语言中的小细节你get到了吗?(java二维数组与c二维数组的不同、动态数组、Scanner)
这些编程语言中的小细节你get到了吗?(java二维数组与c二维数组的不同、动态数组、Scanner)
|
IDE Java 开发工具
Java-创建一个自定义窗口,扁平化界面
Java-创建一个自定义窗口,扁平化界面
260 0
Java-用简单方法创建透明窗口
Java-用简单方法创建透明窗口
346 0
|
Java 程序员
Java面向对象8——接口(内含IDEA中有关创建接口的创建说明)
上一次我们说了抽象方法的存在是因为父类可以抽取子类中的共性方法,但是共性方法内实现方法不同所以要将共性方法写成抽象方法,那么如果子类中有一个“另类”不需要这个方法的话,我们就无法使用抽象方法了,而是要使用接口,哪个子类需要用,就继承该接口
390 0
Java面向对象8——接口(内含IDEA中有关创建接口的创建说明)