1.该类主要实现了ArrayList主要的几个方法:add()、remove()、size()、get()
package cn.sxt.oop.collection;
/**
* 自己实现一个ArrayList
* @author 2018-8-03
* 主要方法:size()、add()、remove()、get()
public class ArrayListTest01 {
//声明一个Object类型的数组
private Object[] elementDate;
//声明一个数组内元素个数
private int size;
public int size() {
return size;
}
//定义一个无参构造函数,初始化数组内个数
public ArrayListTest01(){
this(10);//调用另一个构造方法(有参构造方法),所以,必须有一个有参构造方法
}
public ArrayListTest01(int initialCapacity) {//有参构造方法,实现数组容量的初始化
if(initialCapacity<0) {
try {
throw new Exception();
}catch(Exception e){
e.printStackTrace();
}
}
elementDate=new Object[initialCapacity];//初始化,容量为10 与前面的数组声明对应
}
//重点***********
public void add(Object obj) {
//首先,判断数组是否装满,是则扩容
elementDate[size++]=obj;
if(size==elementDate.length) {
//创建一个新数组
Object[] newArray=new Object[2*size+1];
//将老数组拷贝到新数组内
System.arraycopy(elementDate, 0, newArray, 0, elementDate.length);
//再将新数组赋值给老数组
elementDate=newArray;
}
}
//get方法,得到数组实质就是一个数组的索引操作
public Object get(int index) {
//检查下标是否越界
rangCheck(index);
return elementDate[index];
}
public void remove(int index){
rangCheck(index);
//删除指定位置对象,删除某位置,相当于 将后往前挪:
int numMoved = size-index-1;
if(numMoved>0){
System.arraycopy(elementDate, index+1, elementDate, index, numMoved);
}
}
public void remove(Object obj){
for(int i=0;i<size;i++){
if(get(i).equals(obj)){ //注意底层调用的equals方法而不是==。
remove(i);
}
}
}
private void rangCheck(int index) {
if(index<0||index>size) {
try {
throw new Exception();
}catch(Exception e) {
e.printStackTrace();
}
}
}
public void add(int index,Object obj) {
rangCheck(index);
ensureCapacity();//扩容
System.arraycopy(elementDate,index,elementDate, index+1, size-index);
elementDate[index]=obj;
size++;
}
private void ensureCapacity() {
if(size==elementDate.length) {
Object[] newarray=new Object[size*2+1];
System.arraycopy(elementDate, 0, newarray, 0, elementDate.length);
elementDate=newarray;
}
}
public static void main(String[] args) {
ArrayListTest01 list=new ArrayListTest01();
list.add("温暖");
list.add("依然");
list.add("wk");
list.add("wk1");
list.add("wk2");
System.out.println("list内拥有:"+list.size()+"个元素");
}
}
2.涉及知识点
① 数组声明与创建
数组声明:数组在使用前需要先声明,指定数组中存放的数据类型和名字,本文应用如下:
private Object[] elementDate;
数组创建:数组声明后,需要创建才能使用。创建数组就是指定数组可以存放的数据(元素),并分配对应大小的内存空间。本文应用如下
elementDate=new Object[initialCapacity];
②this方法的用法
主要有三种用法:
⑴ 使用this关键字引用成员变量
⑵ 使用this关键字引用成员方法
⑶ 使用this关键字在自身构造方法内部引用其它构造方法
提示:this关键字代表自身类的对象(实例)
本文应用如下:
public ArrayListTest01(){
this(10);//上面方法⑶的应用,调用下面的有参构造方法
}
public ArrayListTest01(int initialCapacity) {
if(initialCapacity<0) {
try {
throw new Exception();
}catch(Exception e){
e.printStackTrace();
}
}
elementDate=new Object[initialCapacity];
}
③“==”的用法
两种主要用途:
⑴比较基本数据类型(byte、short 、int、long、float、double、char、boolean)
== 表示数量相等(值相等),由于不是对象,所以不能使用equals()方法,
⑵比较符合数据类型(类)
== 比较的是他们在内存中的地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。
public void add(Object obj) {
elementDate[size++]=obj;
if(size==elementDate.length) {//上面方法(1)的应用,比较的是基本类型
Object[] newArray=new Object[2*size+1];
System.arraycopy(elementDate, 0, newArray, 0, elementDate.length);/
elementDate=newArray;
}
}
④ equal()的用法
⑴ 对于字符串来说是比较内容的
⑵ 对于非字符串来说是,比较其指向的对象是否相同。
public void remove(Object obj){
for(int i=0;i<size;i++){
if(get(i).equals(obj)){ //注意底层调用的equals方法而不是==。
//比较的是两个对象的值是否相等,不是地址
remove(i);
}
}
}
⑤ 异常处理
Java的“异常”处理是通过try、catch、throw、throws和finally5个关键字来实现的。
⑴ try…catch..方法的使用
把可能引发异常的代码放进一个try块中,try块后面应包含一个或多个catch子句来指定用户想要捕捉的“异常”的类型。
⑵ throw抛出异常的使用(注意与throws对比,区别)
private void rangCheck(int index) {
if(index<0||index>size) {
try {
throw new Exception();//throw 抛出具体的异常
}catch(Exception e) {
e.printStackTrace();
}
}
⑥ 还用到方法、类、字符串拷贝、权限修饰符、基本数据类型的使用等相关知识。
3. 思考与体会
1.ArrayList底层实现是基于数组实现的。所以,获取元素时,就是利用数组的下标索引返回目标对象,故,其查询速度比较快。如下:
public Object get(int index) {
//检查下标是否越界
rangCheck(index);
return elementDate[index];//采用数组的下标索引
}
2.ArrayList自动改变大小的功能其实就是数组的拷贝问题。
具体操作可以分为以下几步:
①判断数组是否装满
②装满就创建一个新的数组,该新数组是原来数组的2倍加1(源码就是如此,我们自己设计时,可以自行决定)
③将老数组的内容拷贝到新数组中,
④再将新数组赋值给老数组名(以便重复使用老数组名字)
这样不断循环,就实现了数组的不断扩容。
public void add(Object obj) {
//①首先,判断数组是否装满,是则扩容
elementDate[size++]=obj;
if(size==elementDate.length) {
//②创建一个新数组
Object[] newArray=new Object[2*size+1];
//③将老数组拷贝到新数组内
System.arraycopy(elementDate, 0, newArray, 0, elementDate.length);
//④再将新数组赋值给老数组
elementDate=newArray;
}
}
3. 难点与重点
掌握add()和remove()。
该实现类,还不够完善,但是,对于我们理解ArrayList的原理和后续看其源码有很大的帮助。