java集合框架
首先我觉得你想掌握java集合的话应该先了解java集合框架的组成关系,啥都不多说直接上个老图。。。一、Map集合
实现Map接口的集合有多种,常用的:HashMap、TreeMap以及上图没有列出来的HashTable和LinkedHashMapMap集合的共同点:都是键值对的形式保存数据,而且Map集合中不能有相同的键。每一个键都对应着一个值(key与value)
Map集合中的数据在物理内存中存的位置是根据key通过一系列复杂的计算来得到的hashcode(散列码hashcode)值来选择存取位置。
至于Map常用的方法大家可以参考一下下边HashMap的代码
hashcode与equals
hashcode与equals这两个方法都是在object类中定义的,object类是所有类的基类,因此所有的类对象都具有这两个方法。
在说hashcode之前呢必须得先说一下equals方法
查阅object的源码我们可以发现,equals方法比较的是两个对象的地址,也就是说在object类中,equals与==比较的结果是一样的,而为什么Integer a1 = new Integer(10);Integer a2 = new Integer(10);a1.equals(a2)返回是的是true而a1==a2返回的是false呢?因为基本上很多自带的类库都已经重写了equals方法,而且修改后的equals方法比较的是对象的内容,而==依旧是比较的地址。所以便有了以上的结果。
hashcode是什么,hashcode又名散列码,是经过一系列的复杂计算的出来的一个int值。这个值跟这个对象相互对应有着一对一的关系,每一个散列码都对应着一个对象,每一个对象都对应着一个散列码,但是并不是所有不同的对象产生的散列码都不是相等的。
偶尔也会出现两个不同的对象计算得到的散列码是相等的情况,这种情况叫做碰撞(哈希冲突)
HashMap解决这种碰撞的方法是链地址法
每一个重写了object类equals方法的类都建议重写hashcode方法。
对于hashcode与equals的关系下边一句话就可以说的明白。好好体会。。。
(暂且将调用equals返回true的两个对象认定为相等)
在Map集合中,相等的对象一定会产生相同的散列码。不等价的对象,不要求产生的散列码不相同。
HashMap
介绍一下HashMap访问速度很快、元素无序排列、可以存一个null key多个null value、线程不同步、数据量大且空数据多遍历慢、遍历速度与容量有关。
跪献HashMap的测试代码(下边其他的Map集合我就不一一贴出来了,这些集合类都实现了Map接口,所以方法大概都一样我只说一下需要注意的区别)
package 集合类;
import java.util.*;
import static java.lang.System.out;
public class HashMapTest {
static Map<Integer,String> hs = new HashMap<Integer,String>();
static int count = 0;
public static void main(String[] args) {
// TODO Auto-generated method stub
putHashMap();
getHashMap();
removeHashMap(2);
getHashMap();
removeHashMap();
getHashMap();
}
public static void putHashMap(){
hs.put(1,"one");
hs.put(2,"two");
hs.put(3,"three");
hs.put(4,null);
hs.put(null,null);
hs.put(0,"zero");
hs.put(1,"I am the one");
}
public static void getHashMap(){
count++;
out.println("第"+count+"次输出");
if(hs.isEmpty()){
return;
}
for(Integer i:hs.keySet()){
out.print(i+" ");
out.println(hs.get(i));
}
}
public static void removeHashMap(){
hs.clear();
}
public static void removeHashMap(int key){
if(hs.containsKey(key)){
hs.remove(key);
}else{
out.println(key+"不存在");
}
}
}
运行结果如下:
第1次输出
null null
0 zero
1 I am the one
2 two
3 three
4 null
第2次输出
null null
0 zero
1 I am the one
3 threet
4 null
第3次输出
经过测试我们可以知道,如果向一个hashMap集合中存放一个已经存在的key,那么已存在的这个键值对的值将会被新的值取代。可以有两个null value,只能有一个null key
Hashtable:
与HashMap比不允许有nullkey和nullValue、支持线程同步(线程同步又是比较复杂的一块。。。)
如果往Hashtable中存放nullkey或者null值则抛出异常。(如图)
LinkedHashMap:
HashMap的子类、元素有序排列、数据量大且空数据多遍历速度快遍历速度与实际数据有关,其他操作基本与HashMap相同。(这个类我没有用到过,没有什么经验,暂且不多解释,不误导大家了。)
TreeMap:
默认按照键的升序排序,遍历得到的数据是有序的
如果想详细了解TreeMap的话建议访问下边这个网站。
https://blog.csdn.net/chenssy/article/details/26668941
HashMap与Hashtable
①继承不同。
public class Hashtable extends Dictionaryimplements Map public class HashMap extends AbstractMap implements Map
②Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。
③Hashtable中,key和value都不允许出现null值。
在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
④两个遍历方式的内部实现上不同。
Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
⑤哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。
⑥Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
二、Collection集合
Collection被两个接口实现,他们分别是Set与List
List集合是有序的集合,里面可以存放重复的元素,可以存放null
Set集合是无序的集合,里面不可以存放重复的元素,可以存放null
(这里插一句话曾经有个朋友去面试时被面试官问如果有大量手机号需要去重,设计一个算法实现,要求时间复杂度最低。
朋友只能弱弱的说一个嵌套for循环。。。其实更好的方法是用Set集合接收这些手机号,因为Set集合自带去重。哇!)
1、List集合
List集合常用的有:ArrayList、LinkedList、Vector
ArrayList与LinkedList
ArrayList随机访问速度快(因为是数组结构),插入删除速度慢(因为是数组结构)
LinkedList随机访问速度快(因为是链表结构),插入删除速度慢(因为是链表结构)Vector与ArrayList
ArrayList 线程不安全初始容量是10 每次增长百分之五十 增长后的容量为( 新容量=((旧容量 * 3) / 2) + 1) 扩容0.5倍+1 舍去小数Vector 线程安全初始容量是10 每次增长百分之百 增长后的容量为 (新容量=(旧容量 * 2))扩容1倍
ArrayList与Vector都有构造函数提供设置容量的大小
贴出List集合的代码!!
package GatherTest;
import java.util.*;
public class ListTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<String> al = getAL();
List<String> ll = getLL();
List<String> vr = getVR();
//al
for(int i = 0; i < al.size();i++){
System.out.print(al.get(i)+" ");
}
System.out.println();
//迭代器指定泛型
Iterator<String> it1 = al.iterator();
while(it1.hasNext()){
System.out.print(it1.next()+" ");
}
System.out.println();
//ll
for(int i = 0; i < ll.size();i++){
System.out.print(ll.get(i)+" ");
}
System.out.println();
Iterator<String> it2 = ll.iterator();
while(it2.hasNext()){
System.out.print(it2.next()+" ");
}
System.out.println();
//vr
for(int i = 0; i < vr.size();i++){
System.out.print(vr.get(i)+" ");
}
System.out.println();
Iterator<String> it3 = vr.iterator();
while(it3.hasNext()){
System.out.print(it3.next()+" ");
}
}
public static List<String> getVR(){
List<String> vr = new Vector<String>();
vr.add("vr1");
vr.add("vr2");
vr.add("vr3");
vr.add(null);
return vr;
}
public static List<String> getAL(){
List<String> al = new ArrayList<String>();
al.add("al1");
al.add("al2");
al.add("al3");
al.add(null);
return al;
}
public static List<String> getLL(){
List<String> ll = new LinkedList<String>();
ll.add("ll1");
ll.add("ll2");
ll.add("ll3");
ll.add(null);
return ll;
}
}
2、Set集合
(突然发懒!!。。。未完待续)