一、概述:
1.什么是Collection?它是集合框架的底层,一般不使用。即: Collection是集合层次结构中的根接口,存储的是一组对象,一般不会使用它去操作集合。
2.集合的三个特点:
(1)是否允许有重复元素
(2)是否元素有序【add的顺序和get的顺序是一样的】
(3)是否允许存放null值
3.Collection有很多子接口,而其中最重要最常用的就是List/Set/Queue三个子接口,它们分别对父接口的功能做了各自的扩充~
接下来就具体介绍三个重要子接口中的几个重要分类与具体描述~~
注意只介绍常用分类,其他的以后可能会做另一篇的介绍
二、List
1. ArrayList:最常用的存储形式,熟练运用掌握,编码牢记于心~(1)允许重复元素,是有序的,允许出现空值。 (2)值得注意的是ArrayList的扩容是扩容成1.5倍,底层代码为:
newCapacity = capacity + (capacity>>1)
(3)实现代码:
public class MyArrayList <T>{
private T []element;
private int size;
private final static int defaultCapacity = 10;
public MyArrayList(){
this(defaultCapacity);
this.size = 0;
}
public MyArrayList(int Size){
this.element = (T[])new Object[Size];
this.size = 0;
}
public boolean isEmpty(){
return size ==0;
}
public boolean isOverBoard(){
if(this.element.length == size)
return true;
else
return false;
}
public void growUp(){
this.element= Arrays.copyOf(this.element,this.element.length+1);
}
public void add(T value){
if(isOverBoard())
growUp();
element[size] = value;
size++;
}
public void remove(T value) {
try {
checkRemove();
checkValue(value);
} catch (NoSuchElementException e) {
System.out.println("空的,空的,一滴都没了");
for (int i = 0; i < element.length - 1; i++) {
if (element[i].equals(value)) {
T[] b = Arrays.copyOf(element, element.length - 1);
for (int j = i; j < b.length - 1; j++) {
b[j] = b[j + 1];
}
element = b;
size--;
}
}
}
}
public void set(int index,T newValue){
try{
checkIndex(index);
}catch (NoSuchElementException e){
System.out.print("没这个下标去改变值 ");
System.out.println(e.getMessage());
}
element[index] = newValue;
}
public T get(int index){
try{
checkIndex(index);
}catch (NoSuchElementException e){
//System.out.println("没有这个下标去获取值");
e.printStackTrace();
}
return element[index];
}
public String toString(){
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0;i<size;i++)
stringBuilder.append(element[i]);
return stringBuilder.toString();
}
public void checkIndex(int index) throws NoSuchElementException {
if(index > size-1)
throw new NoSuchElementException();
}
public void checkRemove() throws NoSuchElementException {
if(isEmpty())
throw new NoSuchElementException();
}
public void checkValue(T value) throws NoSuchElementException {
int sum = 0;
for(int i = 0;i<this.size;i++)
if(element[i].equals(value))
sum++;
if (sum == size)
throw new NoSuchElementException();
}
public void show(){
for(int i = 0 ; i< element.length ; i++){
System.out.print(element[i] + " ");
}
System.out.println();
}
}
2.LinkedList:双向循环链表,依然飞飞飞常重要的存储形式,编码要牢记于心!
(1)允许重复元素,是有序的,允许出现空值
(2)实现代码:
public class withHeadLinkedList <E>{
protected Node <E> head;
class Node<E>{
protected E element;
protected Node<E> next;
public Node(E data){
this.element = data;
}
}
public withHeadLinkedList(){
head = new Node<>((E)new Object());
}
//头插法 head之后添加元素
public void addHead(E data){
Node <E> n = new Node(data);
n.next = head.next;
head.next = n;
}
//尾插法
public void addTail(E data){
Node <E> n =new Node(data);
Node taxi = head;
while(taxi.next != null)
{
taxi = taxi.next;
}
taxi.next = n ;
}
public String toString(){
Node <E> taxi = head;
StringBuilder sb = new StringBuilder();
while( taxi.next!=null ){
sb.append(taxi.next.element);
taxi = taxi.next;
}
return sb.toString();
}
public void delete( E data){
Node <E> taxi = head;
if(data == head.element){
head = head.next;
}
while( taxi.next!= null){
if(taxi.next.element == data){
taxi.next = taxi.next.next;
}
else
taxi = taxi.next;
}
}
public E findValue(int index){
Node<E> taxi = head;
int num = 0;
while(taxi.next!= null){
if(num == index)
return taxi.element;
taxi = taxi.next;
num++;
}
return null;
}
public int getLength(){
Node<E> taxi = head;
int size = 0;
while(taxi.next!=null){
taxi = taxi.next;
size++;
}
return size;
}
}
三、Queue
1. ArrayDeque:基于双端队列实现,需要使用队列使使用它时间最快 (1)add,remove,get失败会抛出异常,而与之对应的offer,poll,peek失败会返回null。
(2)允许重复元素,是有序的,不允许出现空值
2.PriorityQueue:源码基于小根堆实现
(1)允许重复元素,不是有序的,不允许出现空值
三、HashMap
综合了数组和链表的优点,是一个查询,插入删除都容易的数据结构。(1)步骤:
①通过hash算法,找到与key对应的存储位置
②访问该位置的value,与当前的value的比较,如果相等就返回,不相等找这个位置对应的链表中的值。
(2)常用hash算法:
加法,乘法,除法,取模法,位运算法等等。
(3)哈希冲突的解决:(在另一篇博客里介绍了,这里不重复)
(4)rehash:
1)为什么要rehash?:之所以要rehash是因为扩容后hash中因为用到了table.length,所以hash出的值一定不一样了,所以要重新hash.
2)rehash之后?:rehash之后可能还在原来的下标,也可能在index+原来table.length的坐标里。
四、Set
1.HashSet:按哈希算法存取对象,速度较快。
2.TreeSet :实现了SortedSet接口,可以对对象排序 ~
3.Set的类都不允许重复元素的出现,且元素是无序的,可以出现null值,但只能出现一次。