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

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

动态数组(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<E> {
//动态数组至少应该有数组的长度和元素的索引两个成员变量。
/**
* 元素的数量
*/
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();
}
}

动态数组java实现的更多相关文章

  1. 常用数据结构-线性表及Java 动态数组 深究

    [Java心得总结六]Java容器中——Collection在前面自己总结的一篇博文中对Collection的框架结构做了整理,这里深究一下Java中list的实现方式 1.动态数组 In compu ...

  2. Java动态数组

    其中java动态数组: Java动态数组是一种可以任意伸缩数组长度的对象,在Java中比较常用的是ArrayList,ArrayList是javaAPI中自带的java.util.ArrayList. ...

  3. JAVA数据结构--ArrayList动态数组

    在计算机科学中,动态数组,可扩展数组,可调整数组,动态表,可变数组或数组列表是一种随机存取可变大小列表数据结构,允许添加或删除元素.它提供许多现代主流编程语言的标准库.动态数组克服了静态数组的限制,静 ...

  4. java动态数组笔记

    动态数组: 在java.lang.reflect包下提供了Array类,包括一系列static方法,通过这些方法可动态的创建数组.给元素赋值.取出元素值等等 //理解数组引用——下面定义的objs数组 ...

  5. java——时间复杂度、动态数组

    O(n)不一定小于O(n^2),要具体来看,而我们说的这种时间复杂度其实是渐进时间复杂度,描述的是n趋近于无穷的情况. 动态数组的时间复杂度: 添加操作:O(n) addLast()的均摊复杂度为O( ...

  6. 纯数据结构Java实现(1/11)(动态数组)

    我怕说这部分内容太简单后,突然蹦出来一个大佬把我虐到哭,还是悠着点,踏实写 大致内容有: 增删改查,泛型支持,扩容支持,复杂度分析.(铺垫: Java语言中的数组) 基础铺垫 其实没啥好介绍的,顺序存 ...

  7. 三 基于Java动态数组手写队列

    手写队列: package dataStucture2.stackandqueue; import com.lt.datastructure.MaxHeap.Queue; import dataStu ...

  8. 二 基于java动态数组手写栈

    package dataStucture2.stack; import dataStucture2.array.MyDynamicArray; /** * 基于动态数组手写栈 * 设计时,栈中仅栈顶对 ...

  9. 一篇文章让你了解动态数组的数据结构的实现过程(Java 实现)

    目录 数组基础简单回顾 二次封装数组类设计 基本设计 向数组中添加元素 在数组中查询元素和修改元素 数组中的包含.搜索和删除元素 使用泛型使该类更加通用(能够存放 "任意" 数据类 ...

随机推荐

  1. php必须掌握的常用函数

    数学函数 数组函数 字符串函数

  2. Spring的SchedulingConfigurer实现定时任务

    前提:在做业务平台的时候我们经常会遇到,某些跟时间打交道的需要修改状态,比如说在时间区间之前,属于未生效状态,区间之内属于有效期,区间之后,属于过期,或者需要每天 每周 每月,甚至是年为单位的做一些固 ...

  3. dos格式迭代转为unix

    #!/bin/bash function recurse_convert() { local path=$ if [ "$path" == "" ];then ...

  4. Java基础加强笔记——测试、反射、注解

    目录 1. Junit单元测试 2. 反射 3. 注解 Junit单元测试: 测试分类: 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值. 2. 白盒测试:需要写代码的.关注程序具 ...

  5. Django学习路25_ifequal 和 ifnotequal 判断数值是否相等及加减法 {{数值|add 数值}}

    {% ifequal 数值 数值 %} <body> {# 判断是否相等 #} num 当前的值 {{ num }}<br/> {% ifequal num 5 %} {# 判 ...

  6. PHP debug_zval_dump() 函数

    debug_zval_dump 函数用于查看一个变量在zend引擎中的引用计数.类型信息. 版本要求:PHP 4 >= 4.2.0, PHP 5, PHP 7高佣联盟 www.cgewang.c ...

  7. HA模式下的java api访问要点

    在非HA架构的HDFS中,客户端要通过java接口调用HDFS时一般是在JobRunner的类中按照下面的方式: 因为nodename只有一个节点所以会在代码中显式的指明要连接哪一个节点:但是在HA模 ...

  8. 面试题:JVM 堆内存溢出后,其他线程是否可继续工作?

    来源:http://sina.lt/gqaM 最近网上出现一个美团面试题:“一个线程OOM后,其他线程还能运行吗?”.我看网上出现了很多不靠谱的答案.这道题其实很有难度,涉及的知识点有jvm内存分配. ...

  9. MySQL8.0.20安装配置+用Navicat连接详细教程(win10,Navicat15)

    MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用 ...

  10. 在图像中隐藏数据:用 Python 来实现图像隐写术

    什么是“隐写术”? 隐写术是将机密信息隐藏在更大的信息中,使别人无法知道隐藏信息的存在以及隐藏信息内容的过程.隐写术的目的是保证双方之间的机密交流.与隐藏机密信息内容的密码学不同,隐写术隐瞒了传达消息 ...