ArrayList
1、ArrayList底层是使用数据实现的存储(动态数组)
2、数组的特点:数组在内存中是一段连续的空间,每个元素都有一个下标,数组一旦创建,容量是不可以改变的。
3、根据下标的特性:查询效率较高,而增加和删除元素就会导致数据发生移动(创建新数组,将旧数组中数据拷贝到新数组中),大量的数据在增加或者删除就会很消耗性能
4、ArrayList是线程不安全的。
通过ArrayList源码分析
1、ArrayList的成员变量 elementData,是一个Object类型的数组
2、size:集合的个数
3、默认容量 DEFAULT_CAPACITY = 10 ;
自定义 ArrayList01
-
构造方法:在不传值的情况下,默认数组的容量是10
-
构造方法:在给一个容量的前提下,将容器赋给数组
-
增加方法:将元素添加到数组中
-
toString方法:将集合中的元素进行遍历,循环打印每一个元素
package com.xw.arrayList;
/**
* 自定义实现ArrayList
*/
public class MyArrayList01 {
private Object[] elementData ;
private int size ;
private static final int DEFAULT_CAPACITY = 10 ;
/**
* 默认值10
*/
public MyArrayList01(){
elementData = new Object[10] ;
}
/**
* 带容量的构造方法
* @param capacity
*/
public MyArrayList01(int capacity){
elementData = new Object[capacity] ;
}
/**
* 添加方法
* @param object
*/
public void add(Object object){
elementData[size++] = object ;
}
public String toString(){
StringBuilder sb = new StringBuilder() ;
sb.append("[");
for(int i=0;i<size;i++){
sb.append(elementData[i]).append(",");
}
sb.append("]");
int i = sb.lastIndexOf(",");
if (i!=-1){
sb.deleteCharAt(i);
}
return sb.toString();
}
public static void main(String[] args) {
MyArrayList01 myArrayList01 = new MyArrayList01(20);
myArrayList01.add("abc");
myArrayList01.add("efg");
myArrayList01.add("hig");
System.out.println(myArrayList01);
}
}
自定义 ArrayList02
- 在第一个的基础上添加泛型
package com.xw.arrayList;
/**
* 添加泛型
* @param <E>
*/
public class MyArrayList02<E> {
private Object[] elementData ;
private int size ;
private static final int DEFAULT_CAPACITY = 10 ;
public MyArrayList02(){
elementData = new Object[10] ;
}
public MyArrayList02(int capacity){
elementData = new Object[capacity] ;
}
/**
* 添加方法
* @param e
*/
public void add(E e){
elementData[size++] = e ;
}
public String toString(){
StringBuilder sb = new StringBuilder() ;
sb.append("[");
for(int i=0;i<size;i++){
sb.append(elementData[i]).append(",");
}
sb.append("]");
int i = sb.lastIndexOf(",");
if (i!=-1){
sb.deleteCharAt(i);
}
return sb.toString();
}
public static void main(String[] args) {
MyArrayList02<String> myArrayList01 = new MyArrayList02<String>(20);
myArrayList01.add("abc");
myArrayList01.add("efg");
myArrayList01.add("hig");
System.out.println(myArrayList01);
}
}
自定义 ArrayList03
思考问题:
1、数组的容量问题,在指定容量之后(20),循环添加操作(21)次,就会出现错误。-> 扩容问题
2、什么时候扩容?:在集合的 size==数组的长度
3、怎么扩容,扩多大:可以将新数组的长度 * /(+)操作,对于计算机底层来说,位运算效率是很高的 我们使用 >>(右移1位相当于除2取余) 或者 << (左移1位相当于*2)
4、其实扩容的本质就是创建新的数组,将旧数组中的数据拷贝到新数组中。
新增的方法
1、扩容
2、设置添加元素,根据指定下标添加元素
3、根据下标获取元素
4、增加一些判断操作
package com.xw.arrayList;
/**
* 增加get set方法
* @param <E>
*/
public class MyArrayList03<E> {
private Object[] elementData ;
// 长度
private int size ;
private static final int DEFAULT_CAPACITY = 10 ;
public MyArrayList03(){
elementData = new Object[10] ;
}
public MyArrayList03(int capacity){
if (capacity<=0){
throw new RuntimeException("容器容量不能为负数");
}else if (capacity == 0){
elementData = new Object[DEFAULT_CAPACITY];
}else {
elementData = new Object[capacity] ;
}
}
/**
* 添加方法
* @param e
*/
public void add(E e){
// 什么时候扩容
if (size==elementData.length){
Object[] newArray = new Object[elementData.length+(elementData.length>>1)];
System.arraycopy(elementData,0,newArray,0,elementData.length);
elementData = newArray ;
}
elementData[size++] = e ;
}
/**
* 获取元素
* @param index
*/
public <E> E get(int index){
if (index<0||index>size-1){ // 10 index 0|0-9
throw new RuntimeException("索引不合法");
}
return (E)elementData[index] ;
}
/**
* 设置值
* @param element
* @param index
*/
public void set(E element,int index){
if (index<0||index>size-1){ // 10 index 0|0-9
throw new RuntimeException("索引不合法");
}
elementData[index] = element ;
}
/**
* toString
* @return
*/
public String toString(){
StringBuilder sb = new StringBuilder() ;
sb.append("[");
for(int i=0;i<size;i++){
sb.append(elementData[i]).append(",");
}
sb.append("]");
int i = sb.lastIndexOf(",");
if (i!=-1){
sb.deleteCharAt(i);
}
return sb.toString();
}
public static void main(String[] args) {
MyArrayList03<String> myArrayList01 = new MyArrayList03<String>(20);
for (int i = 0; i < 40; i++) {
myArrayList01.add("xing"+i);
}
System.out.println(myArrayList01);
System.out.println(myArrayList01.get(1).toString());
myArrayList01.set("张三女",10);
System.out.println(myArrayList01);
myArrayList01.get(40);
System.out.println(myArrayList01);
}
}
自定义 ArrayList04
删除元素操作:
1、怎么删:本质还是数组的拷贝
删除元素 -> 数组的拷贝
a b c d e f index
a b (c) d e f index+1
2、如何拷贝:就是从删除掉的那个元素的下标+1的位置开始移动
-
elementData:原数组
-
index+1:从哪开始移动
-
elementData:新数组
-
index:新数组的下标开始移动的索引
-
elementMoved:移动多少
int elementMoved = elementData.length-1-index; // 计算个数
System.arraycopy(elementData,index+1,elementData,index,elementMoved);
3、最后一点:数组中最后一个位置空了出来,需要移除,集合的个数需要 --
4、增加的方法
-
根据下标删除元素
-
集合的个数
-
判断是否为空
package com.xw.arrayList;
/**
* 添加remove方法
* size:获取集合的个数
* isEmpty:判断集合是否为空
* @param <E>
*/
public class MyArrayList04<E> {
private Object[] elementData ;
// 个数
private int size ;
private static final int DEFAULT_CAPACITY = 10 ;
public MyArrayList04(){
elementData = new Object[10] ;
}
public MyArrayList04(int capacity){
if (capacity<=0){
throw new RuntimeException("容器容量不能为负数");
}else if (capacity == 0){
elementData = new Object[DEFAULT_CAPACITY];
}else {
elementData = new Object[capacity] ;
}
}
/**
* 添加方法
* @param e
*/
public void add(E e){
// 什么时候扩容
if (size==elementData.length){
Object[] newArray = new Object[elementData.length+(elementData.length>>1)];
System.arraycopy(elementData,0,newArray,0,elementData.length);
elementData = newArray ;
}
elementData[size++] = e ;
}
/**
* 获取元素
* @param index
*/
public <E> E get(int index){
if (index<0||index>size-1){ // 10 index 0|0-9
throw new RuntimeException("索引不合法");
}
return (E)elementData[index] ;
}
/**
* 设置值
* @param element
* @param index
*/
public void set(E element,int index){
if (index<0||index>size-1){ // 10 index 0|0-9
throw new RuntimeException("索引不合法");
}
elementData[index] = element ;
}
/**
* toString
* @return
*/
public String toString(){
StringBuilder sb = new StringBuilder() ;
sb.append("[");
for(int i=0;i<size;i++){
sb.append(elementData[i]).append(",");
}
sb.append("]");
int i = sb.lastIndexOf(",");
if (i!=-1){
sb.deleteCharAt(i);
}
return sb.toString();
}
public void removeElement(E element){
// 循环比较每一个元素
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?true:false;
}
/**
* 根据下标删除元素
* @param index
*/
public void remove(int index){
// 删除元素 -> 数组的拷贝
// a b c d e f index
// a b d e f index+1
int elementMoved = elementData.length-1-index; // 5-2
if (index>0){
System.arraycopy(elementData,index+1,elementData,index,elementMoved);
}
// 移除最后一个元素
elementData[size-1] = null ;
size--;
}
public static void main(String[] args) {
MyArrayList04<String> myArrayList01 = new MyArrayList04<String>(20);
for (int i = 0; i < 40; i++) {
myArrayList01.add("xing"+i);
}
System.out.println(myArrayList01);
System.out.println(myArrayList01.get(1).toString());
myArrayList01.set("张三女",10);
System.out.println(myArrayList01);
myArrayList01.remove(10);
System.out.println(myArrayList01);
System.out.println(myArrayList01.size());
System.out.println(myArrayList01.isEmpty());
// System.out.println(myArrayList01.size-1);
// System.out.println(myArrayList01.elementData.length);
}
}
OK !!!。
下一篇:自定义LinkedList