一,命名规范定义
1,java.util.collection接口来定义数据结构中方法的命名规范。
2,java.util.List此接口是collection的子接口,要求实现此接口的类,必须满足数据是有序且可以重复的特性。
3,java.util.Set此接口是collection的子接口,要求实现此接口的类,必须满足数据是无序且不可重复的特性。
二,数据结构的实现类
List
1,java.util.ArrayList以可变数组长度的方式实现java.util.List接口。
例:
package myutil; /*总结: ArrayList适合查找元素,而不适合 删除、插入元素*/ public class ArrayList { Object[] elementData; int size; public ArrayList(){ this(10); } public ArrayList(int initialCapacity){ if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } public boolean add(Object obj){ this.ensureCapacity(this.size+1); this.elementData[size++] = obj; return true; } /* 由于在数组中删除元素需要调整数组的下标,例如在100个元素中删除第一个元素需要调下标99次, 因此在ArrayList中删除元素的效率很低(特别是删除在数组中靠前的元素)*/ public Object remove(int index){ Object oldEle=this.elementData[index]; for(int i=index;i<size;i++){ this.elementData[i]=this.elementData[i+1]; } size--; return oldEle; } /* 由于可变长度实际上是新数组和原数组之间一个copy,因此效率很低,在创建ArrayList的时候应该尽量使用 第二种构造函数。*/ private void ensureCapacity(int capacity){ if(capacity>this.elementData.length){ Object[] newElementData = new Object[this.elementData.length*3/2];//扩展到1.5倍。 this.copy(newElementData); } } private void copy(Object[] newElementData){ for(int i=0;i<size;i++){ newElementData[i]=this.elementData[i]; } this.elementData=newElementData; } public Object get(int index){ return this.elementData[index]; } public int size(){ return this.size; } }
2,java.uti.LinkedList以链表的方式实现java.util.List接口。
例:
package myutil; import java.util.Collection; import java.util.Iterator; /*总结:由于LikedList由链表实现(对象的引用),因此在删除链表头或尾部元素的时候效率非常高,这刚好与ArrayList相反 LinkedList的遍历应该按照java.util.Iterator(迭代器规)规范实现遍历,这种方式是从链表表的头部往next或previous顺序返回数据, 效率与ArrayList相同,因此如果要遍历LinkedList应该使用迭代器而不是get方法。 * * */ public class LinkedList implements Iterable { Node header = new Node(null); int size; public LinkedList(){ this.header.previous = header.next = header; } public Iterator iterator(){ class IteratorImp implements Iterator{ Node ele=header; @Override public boolean hasNext() { return ele.next!=header; } @Override public Object next() { Node n=ele.next; ele=n; return n.ele ; } @Override public void remove() { } } return new IteratorImp(); } public boolean add(Object ele){ Node newNode = new Node(ele); newNode.previous = header.previous; newNode.next = header; header.previous.next = newNode; header.previous = newNode; size++; return true; } private Node node =header; public boolean add2(Object ele){ Node newNode = new Node(ele); header.previous = newNode; node.next = newNode; newNode.previous = node; newNode.next = header; node = newNode; size++; return true; } public void removeFirst(){ Node removeEle=header.next; removeEle.next.previous = header; header.next = removeEle.next; removeEle = removeEle.previous = removeEle.next = null; size--; } public void removeLast(){ } //查找元素时效率低,需要对链表进行遍历。ArrayList效率高因为数组可以快速定位到指定下标的元素。 public Object get(int index){ if(index < size>>1){ Node node=header; for(int i=0;i<=index;i++){ node=node.next; } return node.ele; }else{ Node node=header; for(int i=size;i>index;i--) { node = node.previous; } return node.ele; } } public int size(){ return this.size; } class Node{ Node next; Node previous; Object ele; Node(Object ele){ this.ele =ele; } } }
Set
1,java.util.HashSet HashSet由HashMap实现,把所有元素都储存在HashMap的key中。(此实现依照HashMap方法实现)
Map
(map是key-value的数据储存关系,与集合接口没有任何关联)
1,常用实现类java.util.HashMap
例:
package myutil; import java.util.Iterator; @SuppressWarnings("all") public class HashMap{ static final int DEFAULT_INITIAL_CAPACITY = 16; static final float DEFAULT_LOAD_FACTOR = 0.75f; Node[] elementsData; public int threshold; int size; public HashMap(int initialCapacity, float loadFactor) { this.threshold= (int)(initialCapacity*loadFactor); } public HashMap(){ this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); this.elementsData = new Node[8]; init(); } public Object get(Object key){ int index= indexFor(key.hashCode()); Node ele=this.elementsData[index]; for(; ele!=null;ele=ele.next){ if(ele.key==key) return ele.value; } return null; } public Object put(Object key, Object value){ if(size+1>threshold){ //reHash 扩展Hash表的长度。 } return addNode(key,value); } public void init(){ } public Node addNode(Object key, Object value){ Node ele=new Node(key,value); int index= indexFor(key.hashCode()); ele.next = this.elementsData[index]; this.elementsData[index]=ele; size++; return ele; } public int indexFor(int h) { int index=h & (this.elementsData.length-1); if(index<0) index=index*-1; return index; } public static class Node{ Object key; Object value; Node next; public Node(Object key,Object value){ this.key = key; this.value = value; } public Node(){ } } }
2,java.util.LinkedHashMap如果需要使用HashMap的功能又需要对储存的数据进行排序则使用LinkedHashMap。
例:
package myutil; import java.util.Iterator; public class LinkedHashMap extends HashMap implements Iterable { Node header; @Override public void init(){ header=new Node(null,null); header.previous = header.next = header; } @Override public Iterator iterator() { class IteratorImp implements Iterator{ Node ele=header; @Override public boolean hasNext() { return ele.next!=header; } @Override public Object next() { Node n=ele.next; ele=n; return n.value ; } @Override public void remove() { } } return new IteratorImp(); } class Node extends HashMap.Node{ Node previous; Node next; public Node(Object key,Object value){ super(key,value); } public boolean addBefore(){ this.previous = header.previous; this.next = header; header.previous.next = this; header.previous = this; return true; } } /* 重写addNode方法。由于HashMap在调用put方法时会调用addNode方法。因此重写此方法后 LinkedHashMap在调用put方法时会执行重写的addNode,从而将存储元素存储到Hash表的同时, 在添加到双向链表的结构中去。*/ @Override public Node addNode(Object key, Object value){ super.addNode(key,value); Node e = new Node( key, value); e.addBefore(); return e; } }