通过对jdk集合类的源码分析,我们可以自己实现一个与ArrayList、LinkedList和HashSet集合类似的集合类来强化自己对各种集合底层原理的理解。
ArrayList
ArrayList底层为一个数组,所以对其增加,删除比较慢,根据索引查找会比较快。
其中代码如下:
package collection;
/**
* 自己实现一个ArrayList,帮助我们更好的理解ArrayList类的底层结构!
*
*/
public class MyArrayList {
/*
* 元素数组
*/
private Object[] elementData;
/*
* 集合容量大小
*/
private int size;
/**
* 返回该集合的元素的数量
* @return
*/
public int size(){
return size;
}
/**
* 判断该集合是否为空
* @return
*/
public boolean isEmpty(){
return size==0;
}
/**
* 构造器
* @return
*/
public MyArrayList(){
this(10);
}
/**
* 初始构造方法
* @param initialCapacity
*/
public MyArrayList(int initialCapacity){
if(initialCapacity<0){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
elementData = new Object[initialCapacity];
}
/**
* 增加一个元素
* @return
*/
public void add(Object obj){
if(size==elementData.length){
Object[] newArray = new Object[size*2+1];
System.arraycopy(elementData, 0, newArray, 0, elementData.length);
elementData = newArray;
}
elementData[size++]=obj;
}
/**
* 根据索引替换该元素
* @return
*/
public Object set(int index,Object obj){
rangeCheck(index);
Object oldValue = elementData[index];
elementData[index] = obj;
return oldValue;
}
/**
* 根据索引增加元素
* @return
*/
public void add(int index,Object obj){
rangeCheck(index);
ensureCapacity();
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = obj;
size++;
}
/**
* 根据索引获取该元素
* @return
*/
public Object get(int index){
rangeCheck(index);
return elementData[index];
}
/**
* 根据索引删除元素
* @return
*/
public void remove(int index){
rangeCheck(index);
int numMoved = size - index - 1;
if (numMoved > 0){
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
}
elementData[--size] = null;
}
/**
* 根据元素的值删除元素
* @return
*/
public void remove(Object obj){
for(int i=0;i<size;i++){
if(get(i).equals(obj)){
remove(i);
}
}
}
/**
* 数组扩容和数据的拷贝
* @return
*/
private void ensureCapacity(){
if(size==elementData.length){
Object[] newArray = new Object[size*2+1];
System.arraycopy(elementData, 0, newArray, 0, elementData.length);
elementData = newArray;
}
}
/**
* 检查索引是否越界
* @return
*/
private void rangeCheck(int index){
if(index<0||index>=size){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
LinkedList
LinkedList 底层为链表实现,所以是由一个个节点连接而成,每个节点都记录着下一个元素的位置以及上一个元素的位置,所以要实现一个自己的LinkedList 则需要先顶一个节点Node类。
与ArrayList相反,LinkedList增加和删除效率高,而查找效率低。
Node节点类代码如下:
package collection;
public class Node {
/*
* 上一个节点
*/
Node previous;
/*
* 本身的节点
*/
Object obj;
/*
* 下一个节点
*/
Node next;
public Node() {
}
public Node(Node previous, Object obj, Node next) {
super();
this.previous = previous;
this.obj = obj;
this.next = next;
}
public Node getPrevious() {
return previous;
}
public void setPrevious(Node previous) {
this.previous = previous;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
MyLinkedList的代码如下:
package collection;
public class MyLinkedList {
/*
* 链表的第一个节点
*/
private Node first;
/*
* 链表的最后一个节点
*/
private Node last;
/*
* 集合的代大小
*/
private int size;
/**
* 增加一个元素
* @param obj
*/
public void add(Object obj){
Node n = new Node();
if(first==null){
n.setPrevious(null);
n.setObj(obj);
n.setNext(null);
first = n;
last = n;
}else{
//直接往last节点后增加新的节点
n.setPrevious(last);
n.setObj(obj);
n.setNext(null);
last.setNext(n);
last = n;
}
size++;
}
/**
* 返回该元素的大小
* @return
*/
public int size(){
return size;
}
/**
* 检查索引是否越界
* @param index
*/
private void rangeCheck(int index){
if(index<0||index>=size){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 根据索引获取该元素
* @param index
* @return
*/
public Object get(int index){
rangeCheck(index);
Node temp = node(index);
if(temp!=null){
return temp.obj;
}
return null;
}
/**
*
* @param index
* @return
*/
public Node node(int index){
Node temp = null;
if(first!=null){
if (index < (size >> 1)) {
temp = first;
for(int i=0;i<index;i++){
temp = temp.next;
}
}else{
temp = last;
for (int i = size - 1; i > index; i--){
temp = temp.previous;
}
}
}
return temp;
}
/**
* 根据索引删除元素
* @param index
*/
public void remove(int index){
Node temp = node(index);
if(temp!=null){
Node up = temp.previous;
Node down = temp.next;
up.next = down;
down.previous = up;
size--;
}
}
/**
* 根据索引增加元素
* @param index
* @param obj
*/
public void add(int index,Object obj){
Node temp = node(index);
Node newNode = new Node();
newNode.obj = obj;
if(temp!=null){
Node up = temp.previous;
up.next = newNode;
newNode.previous = up;
newNode.next = temp;
temp.previous = newNode;
size++;
}
}
}
HashSet
HashSet 最大不同就是元素不可重复,其实就是利用了map里面键对象的不可重复来实现,所以这里实现自己的HashSet比较简单。
package collection;
import java.util.HashMap;
public class MyHashSet {
HashMap map;
private static final Object PRESENT = new Object();
public MyHashSet(){
map = new HashMap();
}
public int size(){
return map.size();
}
public void add(Object o){
map.put(o, PRESENT);
}
}