List详解
Collection是所有集合的父类,其中包含了List、Map、Set三个接口。如图1.0所示
图1.0.集合的继承关系
List接口的实现
Vector
vetor与数组类似有一段连续的存储,拥有一段连续的内存空间,
随机存取
自动分配工作空间节省空间
但是插入速度较慢,只能在尾部插入,在头部插入或者删除的时候消耗时间规模与容器的大小成正比
当数组内存空间不够时,会重新申请一块内动空间并进行内存拷贝。进行整体的分配的拷贝与释放。
/*
* Vector数据存储
*/
public class vector {
public static void main(String[] args) {
Vector v=new Vector<>();
//void addElement(E obj) 将指定的组件添加到此向量的末尾,将其大小增加 1。
v.addElement("hello");
v.addElement("world");
v.addElement("java");
for(int x=0;x<v.size();x++){
//E elementAt(int index) 返回指定索引处的组件。
String s=(String) v.elementAt(x);
System.out.println(s);
}
}
}
Arraylist
ArrayList是非同步的是线程不安全的
同Vector一样是一个基于数组上的链表,但是不同的是ArrayList不是同步的。所以在性能上要比Vector好一些,但是当运行到多线程环境中时,可需要自己在管理线程的同步问题。ArrayList是实现了基于动态数组的数据结构
ArrayList是线程不安全的因为线程的同步必然会影响线程的执行效率所以ArrayList的性能相对的比Vector好一些
当内存空间不足的时候ArrayList会增加初始容量的50%,这样有利于节约内存空间。
集合的嵌套:
多种不同ArrayList的遍历,将不同的ArrayList放置于大的ArrayList集合中
/*
*ArrayList存储
*/
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<ArrayList<Student>> bigArrayList=new ArrayList<ArrayList<Student>>();
//子集合一
ArrayList<Student> firstArrayList=new ArrayList<Student>();
Student s1=new Student("宋江", 30);
Student s2=new Student("武松", 29);
Student s3=new Student("鲁智深", 28);
Student s4=new Student("李逵", 27);
firstArrayList.add(s1);
firstArrayList.add(s2);
firstArrayList.add(s3);
firstArrayList.add(s4);
bigArrayList.add(firstArrayList);
LinkedList
LinkedList基于双向链表实现,因此不像ArrayList需要扩容机制。
当ArrayList扩容时,会自动生成一个新的array(长度是之前的1.5倍),再将旧的array移值上去,不存在容量不足现象。
由于LinkedList实现了Deque,而Deque接口定义了在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。
LinkedList可以作为FIFO(先进先出)的队列或者LIFO(后进先出)的栈
LinkedList也是线程不安全的
/*
*LinkedList存储
*/
public class LinkedList {
public static void main(String[] args) {
LinkedList link=new LinkedList<>();
link.add("hello");
link.add("world");
link.add("java");
//将指定的元素插入到列表的开头
link.addFirst("say weizhao");
//将指定的元素插入到列表的结尾
link.addLast("last");
//移除并返回此列表的第一个元素
link.removeFirst();
//移除并返回此列表的最后一个元素
link.removeLast();
System.out.println("link:"+link);
//返回第一个/最后一个元素
System.out.println("link.getFirst="+link.getFirst());
System.out.println("link.getLast="+link.getLast());
}
}
LinkedList和ArrayList的区别
1、ArrayList继承于 AbstractList, LinkedList继承于 AbstractSequentialList;
2、ArrayList基于动态数组的数据结构, LinkedList基于双向链表。
3、对于随机访问, ArrayList比较占优势,LinkedList插入、删除元素比较快,如果只要调整指针的指向那么时间复杂度是O(1), 但是如果针对特定位置需要遍历时,时间复杂度是O(n),也就是LinkedList在随机访问元素的话比较慢;
4、LinkedList需要更多的内存,因为 ArrayList的每个索引的位置是实际的数据,而 LinkedList中的每个节点中存储的是实际的数据和前后节点的位置;
5、ArrayList 和 LinkedList都是非同步的集合,都是线程不安全的
6、Linked基于链表因此不需要ArrayList的扩容机制
Set
HashSet
/*
*HashMap存储
*/
public class HashSetDemo {
public static void main(String[] args) {
HashSet<Like> hs=new HashSet<Like>();
Like s1=new Like("唱",1);
Like s2=new Like("跳", 2);
Like s3=new Like("rap", 3);
Like s4=new Like("篮球", 4);
Like s5=new Like("美妆", 5);
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
hs.add(s5);
for(Like s:hs){
System.out.println(s.toString());
}
}
}
定义Like类
/*
*必须同时重写hashCode()和equals()两个方法,才能使相同属性的对象具有相同哈希值。
*/
public class Like implements Comparable<Like>{
private String name;
private int weight;
public Like() {
super();
}
public Like(String name, int weight) {
super();
this.name = name;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getweight() {
return weight;
}
public void setweight(int weight) {
this.weight = weight;
}
public String toString() {
return "Like [name=" + name + ", weight=" + weight + "]";
}
//实现LinkedHashSet排序,必须同时重写hashCode()和equals()两个方法,才能使相同属性的对象具有相同哈希值
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + weight;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Like other = (Like) obj;
if (weight != other.weight)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Map
HashMap和Hashtable的区别
hashMap(数组+链表+红黑树)和Hashtable(链表)的区别:
-
两者继承的类不同,两者都实现了Map接口,但是HashMap继承的是AbstractMap,而Hashtable继承的是Dictionary
-
HashMap中的方法都是非同步的而Hashtable中的方法是同步的,所以HashMap是线程不安全的,Hashtable是线程安全的。在单线程中,HashMap的执行效率却是比Hashtable高
-
HashMap中的put方法允许键值对为空,而Hashtable不可以
Hashtable:底层是vector ,vector中的元素是链表
Vector 代表篮子,初始大小是53当数据超过长度的时候会变大2倍。存节点指针时会经过hash函数找到对应的篮子,然后连在篮子后面 当扩容的时候以前存入的元素会重新分配篮子