一、泛型
1、在JDK1.4以前,所有的集合元素全都按照Object来存储,拿出来还要进行强制转型。由于这样的做法有太多的缺点,容易出现ClassCaseException,不安全,让人不省心,于是乎JDK5之后出现了泛型。
2、什么是泛型,通俗的讲,就是在Java文件编译期对类型进行检查。比如:List<String> string = new ArrayList<String>(); 它只能装String类型的对象,否则编译时报错。
二、自定义ArrayList
1、ArrayList顾名思义,底层就是使用数组实现的List。
2、代码
package com.collection.arrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
//实现Iterable接口,就可以使用forEach
public class MyArrayList<E> implements Iterable<E> {
//Object的数组,Java没有泛型数组
private Object[] elementData = null;
private int size = 0;
//默认的数组大小是10
public MyArrayList() {
this(10);
}
public MyArrayList(int cacaptiy) {
elementData = new Object[cacaptiy];
}
public boolean add(E obj) {
//如果当前元素个数已经跟数组一样大了,就扩容
if(size >= elementData.length) {
this.ensureCapacityInternal(elementData.length);
}
elementData[size++] = obj;
return true;
}
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] arr) {
if(arr.length < size) {
return (T[]) Arrays.copyOf(elementData, size, arr.getClass());
}
System.arraycopy(elementData, 0, arr, 0, arr.length);
if(arr.length > size) {
arr[size] = null;
}
return arr;
}
@SuppressWarnings("unchecked")
public E[] toArray() {
return (E[]) Arrays.copyOf(elementData, elementData.length);
}
public boolean addAll(MyArrayList<E> list) {
for(int i = 0; i < list.size; i++) {
this.add(list.get(i));
}
return true;
}
public boolean set(int index, E obj) {
if(index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
ensureCapacityInternal(1);
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = obj;
size ++;
return true;
}
public boolean remove(int index) {
if(index < 0 || index >= size) {
throw new ArrayIndexOutOfBoundsException();
}
System.arraycopy(elementData, index + 1, elementData, index, size - index -1);
size --;
return true;
}
public boolean remove(E obj) {
for(int i = 0; i < elementData.length; i++) {
if(obj == elementData[i]) {
System.arraycopy(elementData, i + 1, elementData, i, size - i - 1);
size --;
return true;
} else if(obj.equals(elementData[i]) && obj.hashCode() == elementData[i].hashCode()) {
System.arraycopy(elementData, i + 1, elementData, i, size - i - 1);
size --;
return true;
}
}
return false;
}
@SuppressWarnings("unchecked")
public E get(int index) {
if(index < 0 || index >= size) {
throw new ArrayIndexOutOfBoundsException();
}
return (E) elementData[index];
}
public void ensureCapacityInternal(int cacaptiy) {
Object[] newArr = new Object[elementData.length + cacaptiy];
System.arraycopy(elementData, 0, newArr, 0, elementData.length);
elementData = newArr;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void clear() {
for(int i = 0; i <size; i++) {
elementData[i] = null;
}
size = 0;
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E>{
private int cursor = 0;
private int lastRet = -1;
@Override
public boolean hasNext() {
return cursor != size();
}
@SuppressWarnings("unchecked")
@Override
public E next() {
if(cursor == size()) {
throw new NoSuchElementException();
}
lastRet = cursor;
return (E) elementData[cursor ++];
}
public void remove() {
if(lastRet == -1) {
throw new IllegalStateException();
}
MyArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
}
}
}
三、自定义LinkedList
1、LinkedList底层是用链表实现的
2、先定义一个Node类
package com.collection.linkedList;
public class Node {
//前一个节点的引用
private Node prev;
//存储的数据
private Object object;
//下一个节点的引用
private Node next;
public Node getPrev() {
return prev;
}
public void setPrev(Node prev) {
this.prev = prev;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
3、MyLinkedList.java
package com.collection.linkedList;
public class MyLinkedList<E> {
private Node header;//链表的节点头
private Node tail;//链表的结尾
private int size;//记录当前元素的大小
public MyLinkedList() {
}
/**
* 在某个位置插入元素
* @param index
* @param obj
*/
public void set(int index, E obj) {
if(index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
Node node = new Node();
node.setObject(obj);
Node temp1 = header;
Node temp = null;
Node temp2 = tail;
Node prev = null;
//除以,看看这个index离header近还是tail近
if(index >= (size >> 1)) {
for(int i = 0; i < index; i++) {
temp1 = temp1.getNext();
}
temp = temp1;
} else {
for(int i = 0; i < size - index - 1; i++) {
temp2 = temp2.getPrev();
}
temp = temp2;
}
prev = temp.getPrev();
if(prev != null) {
prev.setNext(node);
} else {
header = node;
}
node.setNext(temp);
temp.setPrev(node);
size ++;
}
public boolean remove(int index) {
if(index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
Node temp = header;
for(int i = 0; i < index; i++) {
temp = temp.getNext();
}
Node prev = temp.getPrev();
Node next = temp.getNext();
if(prev != null) {
prev.setNext(next);
} else {
header = next;
}
if(next != null) {
next.setPrev(prev);
} else {
tail = prev;
}
size --;
return true;
}
public boolean remove(Object obj) {
if(obj == null) {
return false;
}
Node temp = header;
Node prev = null;
Node next = null;
while(temp != null) {
if(temp.getObject() == obj) {
prev = temp.getPrev();
next = temp.getNext();
if(prev != null) {
prev.setNext(next);
} else {
header = next;
}
if(next != null) {
next.setPrev(prev);
} else {
tail = prev;
}
size --;
return true;
} else if(temp.getObject().equals(obj) && obj.hashCode() == temp.getObject().hashCode()) {
prev = temp.getPrev();
next = temp.getNext();
if(prev != null) {
prev.setNext(next);
} else {
header = next;
}
if(next != null) {
next.setPrev(prev);
} else {
tail = prev;
}
size --;
return true;
}
temp = temp.getNext();
}
return false;
}
public boolean add(E obj) {
Node node = new Node();
node.setObject(obj);
if(header == null) {
header = node;
header.setPrev(null);
tail = node;
node.setNext(null);
} else {
node.setPrev(tail);
tail.setNext(node);
tail = node;
node.setNext(null);
}
size ++;
return true;
}
@SuppressWarnings("unchecked")
public E get(int index) {
if(index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
Node temp = header;
for(int i = 0; i < index; i++) {
temp = temp.getNext();
}
return (E) temp.getObject();
}
public int size() {
return size;
}
}
四、自定义HashMap
1、HashMap的底层是用数组和链表实现的,数组的元素是链表,链表里存的是键值对对象
2、键值对类MyEntry.java
package com.collection.hashMap;
public class MyEntry {
private Object key;//键
private Object value;//值
public MyEntry(Object key, Object value) {
this.key = key;
this.value = value;
}
public Object getKey() {
return key;
}
public void setKey(Object key) {
this.key = key;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
3、MyHashMap.java
package com.collection.hashMap;
import java.util.LinkedList;
/**
* hashmap是由数组和链表一起构成的
* 由于使用的是hashCode,顺序不能保证,它是无顺序的。
* @author may
*
* @param <E>
* @param <U>
*/
public class MyHashMap<E, U> {
private Object[] elementData = null;
private int size;
private int cacaptiy = 10;
public MyHashMap() {
elementData = new Object[cacaptiy];
}
@SuppressWarnings("unchecked")
public boolean put(E key, U value) {
int hashCode = Math.abs(key.hashCode());
MyEntry entry = new MyEntry(key, value);
LinkedList<MyEntry> linkedList = (LinkedList<MyEntry>) elementData[hashCode % cacaptiy];
//key的hashCode可能会重复,需要做判断
if(linkedList != null) {
boolean flag = false;
for(int i = 0; i < linkedList.size(); i++) {
if(linkedList.get(i).getKey().equals(key)) {
linkedList.get(i).setValue(value);
flag = true;//return;
break;
}
}
if(!flag) {
linkedList.add(entry);
size ++;
}
} else {
linkedList = new LinkedList<MyEntry>();
linkedList.add(entry);
if(size == cacaptiy) {
esureCacaptiy(cacaptiy);
}
elementData[hashCode % cacaptiy] = linkedList;
size ++;
}
return true;
}
public void esureCacaptiy(int increment) {
Object[] obj = new Object[cacaptiy + increment];
cacaptiy = cacaptiy + increment;
System.arraycopy(elementData, 0, obj, 0, elementData.length);
elementData = obj;
}
@SuppressWarnings("unchecked")
public U get(E key) {
int hashCode = key.hashCode();
LinkedList<MyEntry> linkedList = (LinkedList<MyEntry>) elementData[hashCode % cacaptiy];
if(linkedList != null) {
for(int i = 0; i < linkedList.size(); i++) {
if(linkedList.get(i).getKey().equals(key)) {
return (U) linkedList.get(i).getValue();
}
}
}
return null;
}
public int size() {
return size;
}
}
五、自定义HashSet
1、HashSet的底层用的是HashMap,它保存的值就是HashMap里的key
2、代码
package com.collection.hashSet;
import java.util.HashMap;
/**
* HashSet底层是用HashMap实现的,是无序的
* @author may
*
* @param <K>
*/
public class MyHashSet<K> {
private HashMap<K, Object> map = null;
//map的值是固定的
private final static Object PRESENT = new Object();
public boolean add(K obj) {
map.put(obj, PRESENT);
return true;
}
public boolean remove(K obj) {
map.remove(obj);
return true;
}
}