一、Set接口介紹
Set接口繼承Collection接口,而且它不允許集合存在重複項,每個具體的Set實現類依賴添加對象的equlas()和hashCode()方法來檢查獨一性。Set接口沒有引入別的方法,所以Set就是一個Collection,只不過其行爲不同。
二、具體的Set接口的實現
2.1HashSet
HashSet把數據存儲在哈希表中 。哈希表是一種數據結構,用來查找對象。Hash表爲每一個元素計算一個整數,稱爲HashCode(哈希碼)。
Hash底層給個數組,
如將自定義類用 hashSet 來添加對象,一定要覆蓋 hashcode()和 equals(),覆蓋的原則是保證當兩個對象 hashcode 返回相同的整數,而且 equals()返回值爲 True。
重點內容
使用 hashSet 的優點:
hashSet 的底層是數組,其查詢效率非常高。而且在增加和刪除的時候由於運用的 hashCode 的比較開確
定添加元素的位置,所以不存在元素的偏移,所以效率也非常高。因爲 hashSet 查詢和刪除和增加元素
的效率都非常高。
但是 hashSet 增刪的高效率是通過花費大量的空間換來的:因爲空間越大,取餘數相同的情況就越小。
HashSet 這種算法會建立許多無用的空間。
使用 hashSet 接口時要注意,如果發生衝突,就會出現遍歷整個數組的情況,這樣就使得效率非常的
public void test2(){
Set<Integer> set1 = new HashSet<Integer>();
for(int i=0; i<20; ++i){
set1.add(i);
}
Iterator<Integer> it = set1.iterator();
while(it.hasNext()){
System.out.print(it.next() + " ");
}
System.out.println();
}
注意:1.打印set和你插入的數據的順序不一樣!
* 2.往set裏面放自定義類型的對象,一定要重寫兩個函數(equals() hashCode())!否則會出現違背Set中不允許元素重複的原則的情況。
2.2TreeSet
TreeSet是SortedSet的子類,它不同於HashSet的根本就是TreeSet是有序的,是通過SortedMap來實現的。TreeSet放入其中的元素按序存放,這就要求你放入其中的對象是可排序的,一個類是可排序的,它就是實現了Comparable接口。
練習代碼:重寫了Compare方法。使其按從大到小存儲;
public void test5(){
SortedSet<Number> set1 = new TreeSet<Number>(new Comparator<Number>(){
public int compare(Number o1,Number o2){
int res=o1.getValue()-o2.getValue();
return res>0?-1:(res==0?0:1);
}
});
for(int i=20; i>0; --i){
set1.add(new Number(i));
}
Iterator<Number> it = set1.iterator();
while(it.hasNext()){
System.out.print(it.next() + " ");
}
System.out.println();
}
重點內容
HashSet VS TreeSet: HashSet 非常的消耗空間, TreeSet 因爲有排序功能,因此資源消耗非常的高,我們應該儘量少使用,而且最好不要重複使用。
基於以上原因,我們儘可能的運用 HashSet 而不用 TreeSet,除非必須排序。
2.3LinkedHashSet
LinkedHashSet是一個鏈式哈希集合,LinkedHashSet存儲的元素順序和元素插入的順序是一樣的!
練習代碼:
public void test3(){
System.out.println("test3:");
Set<Integer> set1 = new LinkedHashSet<Integer>();
for(int i=0; i<20; ++i){
set1.add(i);
}
Iterator<Integer> it = set1.iterator();
while(it.hasNext()){
System.out.print(it.next() + " ");
}
System.out.println();
}
三、Map接口
Map接口不是Collection接口的繼承。Map接口用於維護鍵/值對,該接口描述了從不重複的到值的映射。
重點內容
注: HashMap 底層也是用數組, HashSet 底層實際上也是HashMap, HashSet 類中有 HashMap 屬性(我們如何在 API 中查屬性)。 HashSet 實際上爲(key.null)類型的 HashMap。有 key 值而沒有 value 值。
HashMap應用
舉例:
請隨機10000個整數,放在LinkedList的裏面 0-200之間的隨機數
請問:如何快速的找出重複次數最多的一個?重複了幾次
請問:如何快速的找出重複次數最多的n個?分別重複了幾次
//測試用例一:重複次數最多的一個
public class TestHashMapDemo {
@Test
public void testHashMap(){
LinkedList<Integer> list=new LinkedList<Integer>();
for(int i=0;i<10000;i++){
list.add((int)(Math.random()*200));
}
LinkedHashMap<Integer, Integer> hashMap = new LinkedHashMap<Integer, Integer>();
for(Integer key:list){
Integer value=hashMap.get(key);
if(value==null){
hashMap.put(key, 1);
}
else{
hashMap.put(key, value+1);
}
}
Integer max=0;
Integer key=null;
Iterator<Entry<Integer, Integer>> it =
hashMap.entrySet().iterator();
while(it.hasNext()){
Entry<Integer,Integer> entry = it.next();
Integer max1 =entry.getValue();
Integer key1= entry.getKey();
if(max1.compareTo(max)>0){
max=max1;
key=key1;
}
}
System.out.println("重複次數最多的是"+key+"重複了多少次:"+max);
}
//測試用例二:重複次數最多的10個
@Test
public void testHashMapMaxTen(){
LinkedList <Integer> list=new LinkedList<Integer>();
for(int i=0;i<10000;i++){
list.add((int)(Math.random()*200));
}
LinkedHashMap<Integer, Integer> hashMap = new LinkedHashMap<Integer, Integer>();
for(Integer key:list){
Integer value=hashMap.get(key);
if(value==null){
hashMap.put(key, 1);
}
else{
hashMap.put(key, value+1);
}
}
//自定義類要排序,利用Compartor接口,實現compareTo方法;
PriorityQueue<Entry<Integer,Integer>> queue=new PriorityQueue<Entry<Integer,Integer>>(10, new Comparator<Entry<Integer,Integer>>(){
public int compare(Entry<Integer,Integer> q1,Entry<Integer,Integer> q2){
return (q1.getValue().compareTo(q2.getValue())>0)?1:(q1.getValue().compareTo(q2.getValue())==0?0:-1);
}
});
Iterator<Entry<Integer, Integer>> it =
hashMap.entrySet().iterator();
int count=0;
while(it.hasNext()){
//int count=0;
Entry<Integer,Integer> entry = it.next();
count++;
if(count<=10){
queue.add(entry);
}
else{
Integer data=queue.peek().getValue(); //peek返回頭部元素
if(entry.getValue().compareTo(data)>=0){
queue.remove();
queue.add(entry);
}
}
}
while(!queue.isEmpty()){
Entry<Integer, Integer> data= queue.peek();
System.out.print("key:"+data.getKey()+" "+"value:"+data.getValue());
System.out.println();
queue.poll();
}
}
}