为了照顾初学者,我分几分版本发出来

版本一:基础版本

实现对象创建、元素添加、重新toString() 方法

package com.xzlf.collection;

/**
* 自定义一个ArrayList,体会底层实现原理
* 初始版本
* @author xzlf
*
* @param <E>
*/
public class MyArrayList<E> {
private Object[] elementDate;
private int size;
private static final int DEFAULT_CAPACITY = 10; public MyArrayList() {
elementDate = new Object[DEFAULT_CAPACITY];
} public MyArrayList(int capacity) {
elementDate = new Object[capacity];
} public void add(E element) {
elementDate[size++] = element;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < size; i++) {
sb.append(elementDate[i] + ",");
}
sb.setCharAt(sb.length() - 1, ']');
return sb.toString();
} public static void main(String[] args) {
MyArrayList<String> list = new MyArrayList<String>(20);
list.add("aa");
list.add("bb");
list.add("cc");
System.out.println(list);
}
}

测试运行

版本二:增加扩容

package com.xzlf.collection;

/**
* 自定义一个ArrayList,体会底层实现原理
* 增加扩容
* @author xzlf
*
* @param <E>
*/
public class MyArrayList2<E> {
private Object[] elementDate;
private int size;
private static final int DEFAULT_CAPACITY = 10; public MyArrayList2() {
elementDate = new Object[DEFAULT_CAPACITY];
} public MyArrayList2(int capacity) {
elementDate = new Object[capacity];
} public void add(E element) {
// 元素个数等于数组长度时 进行扩容操作
if(size == elementDate.length) {
Object[] newArray = new Object[elementDate.length + (elementDate.length >> 1)];
System.arraycopy(elementDate, 0, newArray, 0, elementDate.length);
elementDate = newArray;
}
elementDate[size++] = element;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < size; i++) {
sb.append(elementDate[i] + ",");
}
sb.setCharAt(sb.length() - 1, ']');
return sb.toString();
} public static void main(String[] args) {
MyArrayList2<String> list = new MyArrayList2<String>();
for (int i = 0; i < 15; i++) {
list.add("aa" + i);
}
System.out.println(list);
}
}

测试:

版本三:添加get set方法以及数组边界检查

package com.xzlf.collection;

/**
* 增加get set 方法
* 增加数组边界检查
* @author xzlf
*
* @param <E>
*/
public class MyArrayList3<E> {
private Object[] elementDate;
private int size;
private static final int DEFAULT_CAPACITY = 10; public MyArrayList3() {
elementDate = new Object[DEFAULT_CAPACITY];
} public MyArrayList3(int capacity) {
if(capacity < 0) {
throw new RuntimeException("数组容量不能为负数");
}else if(capacity == 0) {
elementDate = new Object[DEFAULT_CAPACITY];
}
elementDate = new Object[capacity];
} public void add(E element) {
// 元素个数等于数组长度时 进行扩容操作
if(size == elementDate.length) {
Object[] newArray = new Object[elementDate.length + (elementDate.length >> 1)];
System.arraycopy(elementDate, 0, newArray, 0, elementDate.length);
elementDate = newArray;
}
elementDate[size++] = element;
} public E get(int index) {
checkRange(index);
return (E) elementDate[index];
} public void set(E element, int index) {
checkRange(index);
elementDate[index] = element;
} public void checkRange(int index) {
// 索引合法判断[0,size)
if(index < 0 || index > size -1) {
throw new RuntimeException("索引不合法:" + index);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < size; i++) {
sb.append(elementDate[i] + ",");
}
sb.setCharAt(sb.length() - 1, ']');
return sb.toString();
} public static void main(String[] args) {
MyArrayList3<String> list = new MyArrayList3<String>();
for (int i = 0; i < 15; i++) {
list.add("aa" + i);
}
System.out.println(list);
System.out.println(list.get(10));
list.set("bb", 10);
System.out.println(list.get(10));
System.out.println(list.get(-10));
}
}

测试:

版本四:增加remove、size、isEmpty

package com.xzlf.collection;

/**
* 增加remove()
* 增加size isEmpty
* @author xzlf
*
* @param <E>
*/
public class MyArrayList4<E> {
private Object[] elementDate;
private int size;
private static final int DEFAULT_CAPACITY = 10; public MyArrayList4() {
elementDate = new Object[DEFAULT_CAPACITY];
} public MyArrayList4(int capacity) {
if(capacity < 0) {
throw new RuntimeException("数组容量不能为负数");
}else if(capacity == 0) {
elementDate = new Object[DEFAULT_CAPACITY];
}
elementDate = new Object[capacity];
} public void add(E element) {
// 元素个数等于数组长度时 进行扩容操作
if(size == elementDate.length) {
Object[] newArray = new Object[elementDate.length + (elementDate.length >> 1)];
System.arraycopy(elementDate, 0, newArray, 0, elementDate.length);
elementDate = newArray;
}
elementDate[size++] = element;
} public E get(int index) {
checkRange(index);
return (E) elementDate[index];
} public void set(E element, int index) {
checkRange(index);
elementDate[index] = element;
} public void checkRange(int index) {
// 索引合法判断[0,size)
if(index < 0 || index > size -1) {
throw new RuntimeException("索引不合法:" + index);
}
} public void remove(int index) {
int numMoved = size - index -1;
if(numMoved > 0) {
System.arraycopy(elementDate, index+1, elementDate, index, numMoved);
}
elementDate[--size] = null;
} public void remove(E element) {
// 遍历所有元素,和传入的element比较,获取第一个为true的位置 删除
for (int i = 0; i < size; i++) {
if(element.equals(get(i))) {
remove(i);
}
}
} public int size() {
return size;
} public boolean isEmpty() {
return size == 0;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < size; i++) {
sb.append(elementDate[i] + ",");
}
sb.setCharAt(sb.length() - 1, ']');
return sb.toString();
} public static void main(String[] args) {
MyArrayList4<String> list = new MyArrayList4<String>();
for (int i = 0; i < 15; i++) {
list.add("aa" + i);
}
System.out.println(list);
list.remove("aa7");
System.out.println(list);
list.remove(3);
System.out.println(list);
System.out.println(list.size());
System.out.println(list.isEmpty());
}
}

测试:

理解java容器底层原理--手动实现ArrayList的更多相关文章

  1. 理解java容器底层原理--手动实现HashMap

    HashMap结构 HashMap的底层是数组+链表,百度百科找了张图: 先写个链表节点的类 package com.xzlf.collection2; public class Node { int ...

  2. 理解java容器底层原理--手动实现HashSet

    HashSet的底层其实就是HashMap,换句话说HashSet就是简化版的HashMap. 直接上代码: package com.xzlf.collection2; import java.uti ...

  3. 理解java容器底层原理--手动实现LinkedList

    Node java 中的 LIinkedList 的数据结构是链表,而链表中每一个元素是节点. 我们先定义一下节点: package com.xzlf.collection; public class ...

  4. (前篇:NIO系列 推荐阅读) Java NIO 底层原理

    出处: Java NIO 底层原理 目录 1.1. Java IO读写原理 1.1.1. 内核缓冲与进程缓冲区 1.1.2. java IO读写的底层流程 1.2. 四种主要的IO模型 1.3. 同步 ...

  5. Java面试底层原理

    面试发现经常有些重复的面试问题,自己也应该学会记录下来,最好自己能做成笔记,在下一次面的时候说得有条不紊,深入具体,面试官想必也很开心.以下是我个人总结,请参考: HashSet底层原理:(问了大几率 ...

  6. Java 容器 & 泛型:二、ArrayList 、LinkedList和Vector比较

    Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 继续上一篇的容器文章认识容器,泥瓦匠慢慢带你们走进List的容器解说.今天泥瓦匠想说说 ArrayLi ...

  7. 10分钟看懂, Java NIO 底层原理

    目录 写在前面 1.1. Java IO读写原理 1.1.1. 内核缓冲与进程缓冲区 1.1.2. java IO读写的底层流程 1.2. 四种主要的IO模型 1.3. 同步阻塞IO(Blocking ...

  8. Java 总结 数据底层原理 【包括 ArrayList、LinkedList、hash table、HashMap、Hashtable、ConcurrentHashMap、hash code、HashSet、LinkedHashMap、LinkedHashSet】

    1.ArrayList (1)底层是由动态数组实现的[使用了List接口]. (2)动态数组是长度不固定,随着数据的增多而变长. (3)如果不指定,默认长度为10,当添加的元素超过当前数组的长度时,会 ...

  9. Java 容器源码分析之 ArrayList

    概览 ArrayList是最常使用的集合类之一了.在JDK文档中对ArrayList的描述是:ArrayList是对list接口的一种基于可变数组的实现.ArrayList类的声明如下: 12 pub ...

随机推荐

  1. SpringBoot 监控中心

    1,SpringBoot 监控中心: 针对微服务服务监控,服务器内存内存变化(对内存,线程,日志管理),检测服务配置连接地址是否可用(模拟访问,懒加载),故意将mysql 数据源连接密码写错,启动就会 ...

  2. 关于C#中Partial局部类型关键字的使用

    虽然之前在做Winform开发时候,经常遇到Partial关键字,但是最近在代码中看到使用Partial将同名类文件写在多个源文件中,因此想要记录下Partial的详细使用. Partial type ...

  3. [bzoj4472][树形DP] Salesman

    题目 原地址 解说 刚看完这道题感觉还是挺乱的,可能那时候脑子不太清醒,一度觉得自己又要重拾Tarjan了.当然最后还是发觉应该用树形DP. (以下dp[u]代表以u为根的包括自己在内的子树的最大利润 ...

  4. 1008 Elevator (20 分)

    The highest building in our city has only one elevator. A request list is made up with N positive nu ...

  5. 解决MySQL workbench的resultgird不出现的问题

    23:01:37 2019-08-08 鸽了好久 终于开始看怎么使用MySQL workbench了 首先就是遇到了result gird不显示的问题 搜了 重启是一种办法(这方法...至少能用) 其 ...

  6. PTA数据结构与算法题目集(中文) 7-10

    PTA数据结构与算法题目集(中文)  7-10 7-10 公路村村通 (30 分)   现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低 ...

  7. HTML5+CSS+JQuery 实现简单的进度条功能

    样式: <style type="text/css"> .processcontainer2{ width:450px; border:1px solid #6C9C2 ...

  8. ELK数据批量导入

                                                                            数据批量导入 • 使用 _bulk 批量导入数据 – 批 ...

  9. 修改linux服务器名称

    临时修改: hostname test //退出shell,在进入即可修改成功 永久修改 CentOs: vi /etc/hostname //直接+名字即可 //Ubuntu 系统 /etc/hos ...

  10. C语言 文件操作(一)

    #include<stdio.h> int main(){          FILE *fp = fopen("f:\\lanyue.txt","r&quo ...