一、COllections.sort內部原理
Collection.sort()排序通過泛化實現對所有類型的排序,對於基礎類型如int,string,按照字符表,數字大小排序。對於自定義類型,通過實現Comparable接口,重寫comparableTo()方法自定義比較大小的方式。也可以使用Comparator外比較器,Comparable接口的方式比實現Comparator接口的耦合性要強一些。
Collection.sort內部調用的是Arrays.sort方法,對於Arrays類,有兩個sort方法,sort(Object)和sort(int),前者使用歸併排序,後者使用快排。
import java.util.*;
class xd{
int a;
int b;
xd(int a,int b){
this.a=a;
this.b=b;
}
}
public class Main(){
public static void main(String[] args){
xd a=new xd(2,3);
xd b=new xd(4,1);
xd c=new xd(1,2);
ArrayList<xd> list=new ArrayList<>();
array.add(a);
array.add(b);
array.add(c);
Collections.sort(array,new Comparator<xd>(){
@Override
public int compare(xd o1,xd o2){
if(o1.a>o2.a)
return 1;
else if(o1.a<o2.a)
return -1;
return 0;
}
});
for(int i=0;i<array.size();i++)
System.out.println(array.get(i).a);
for(int i=0;i<array.size();i++)
System.out.println(array.get(i).b);
}
}
二、TreeMap和TreeSet
TreeMap和TreeSet都是Java Collection Framework的兩個重要成員,其中TreeMap實現了Map接口,TreeSet實現了set接口。TreeSet底層是通過TreeMap來實現的。二者的實現方式完全一樣,而TreeMap的實現就是紅黑樹算法。
- TreeMap和TreeSet都是有序的集合,它們存儲的值都是排好序的
- TreeMap和TreeSet都是非同步的集合,他們不能再多線程之間共享,不過可以使用Collections.synchronizedMap()來實現同步
- 運行速度都比Hash集合慢,時間複雜度爲O(logN)。而HashMap/HashSet則爲O(1)。
- TreeSet實現了Set接口而TreeMap實現了Map接口。
- TreeSet只存儲一個對象,而TreeMap存儲兩個對象key和Value。
- TreeSet中不能有重複對象,而TreeMap可以有重複對象。
三、集合和有序集合有什麼區別?
有序集合裏的元素可以根據key或index訪問,有序集合在屬性的增加、刪除、修改中擁有較好的性能。
無序集合裏的元素只能遍歷。
- 無序集:set
- 有序集:List
凡是實現set的AbstractSet、CopyOnWriteArraySet、EnumSet、HashSet、LinkedHashSet、TreeSet都是無序的
凡是實現List的AbstractList、ArrayList、LinkedList、Stack、Vector都是有序的
- Map:Map可以根據key來訪問,從這個角度將,Map也是有序的
四、Set是無序的,怎麼保證有序
Set是無序的,但是TreeSet可以保證有序。
五、Java集合框架
Java集合大致可以分爲Set、List、Queue和Map四種體系。其中Set代表無序,不可重複的集合。List代表有序,可以重複的集合。Map代表映射關係的集合。Java5又增加了Queue體系,代表一種隊列集合實現。
Java集合和數組的區別:
數組元素在初始化時指定,意味着只能保存定長的數據。而集合可以保存數量不確定的數據。數組元素既可以保存基本類型的值,也可以是對象。集合裏只能保存對象。基本數據類型要轉換成對應的包裝類才能放入集合類中。
Java集合類之間的繼承關係:Java的集合類主要由兩個接口派生而出:Collection和Map。
Map實現類用於保存具有映射關係的數據。Map保存的每項數據都是key-value對,也就是由key和value兩個值組成。
六、Iterator和ListIterator的區別是什麼
Iterator可以用來遍歷Set和List集合,但是ListIterator只能遍歷List。Iterator對集合只能是前向遍歷,ListIterator既可以前向也可以後向。
七、快速失敗和安全失敗的區別是什麼
Iterator的安全失敗是基於對底層集合做拷貝,它不受源集合上修改的影響。Java.concurrent包下面的所有類都是安全失敗的。而快速失敗受到源集合修改的影響,Java.util包下面的所有集合類都是快速失敗的。快速失敗的迭代器會拋出ConcurrentModificationException異常,而安全失敗的迭代器不會拋出此異常。
八、Java哪些類是線程安全的
Vector:比ArrayList多了個同步機制(Synchronized)
HashTable:HashMap的線程安全版本
Stack:Stack也是線程安全的,繼承與Vector
九、Volatile和synchronized區別
- 加鎖機制既可以保證可見性又可以保證原子性,而volatile只能確保可見性,不能保證原子性
- volatile不會進行加鎖操作。volatile變量是一種稍弱的同步機制在訪問volatile變量時不會執行加鎖操作。也就不會使線程阻塞,因此volatile是一種比Synchronized更輕量級的同步機制。
- volatile不如synchronized安全。
十、Volatile
volatile關鍵字保證了內存可見性,防止指令重排序。volatile並不保證原子性。
- volatile保證內存可見性的原理是每次訪問變量時都會進行一次刷新,因此每次訪問都是主內存中最新的版本。所以volatile關鍵字的作用之一就是保證變量修改的實時可見性。
- 由於volatile屏蔽掉了JVM中必要的代碼優化,所以在效率上比較低。
十一、Java編寫一個會導致死鎖的程序
public static void main(String[] args){
final Object a=new Object();
final Object b=new Object();
Thread threadA=new Thread(new Runnable(){
@Override
public void run(){
synchronized(a){
try{
Thread.sleep(5000);
synchronized(b){
Thread.sleep(1000);
System.out.println("鎖住b");
}
}
catch(Exception e){
e.printStackTrace();
}
}
});
Thread threadB=new Thread(new Runnable(){
@Override
public void run(){
synchronized(b){
try{
Thread.sleep(5000);
Synchroninzed(a){
Thread.sleep(1000);
System.out.println(“鎖住A”);
}catch(Exception e){
e.printStackTrace();
}
});
ThreadA.start();
ThreadB.start();
}
十二、自旋鎖、偏向鎖、輕量級鎖、重量級鎖
阻塞操作會導致在用戶態和內核態之間切換,嚴重影響性能。在很多場景下,同步資源的鎖定時間很短,爲了這一小段時間去切換線程可能會償失,可以讓線程“稍微等待一會”,這就是自旋鎖。
無鎖、偏向鎖、輕量級鎖、重量級鎖都是針對synchronized的。synchronized是悲觀鎖,在操作同步資源之前需要給同步資源加鎖,這把鎖就存在Java對象頭裏面。
一個線程訪問:在大多數情況下,鎖總是由一個線程獲得,不存在多線程競爭,所以出現了偏向鎖。其目標就是在只有一個線程執行同步代碼塊的情況下能夠提高性能
輕量級鎖:兩個線程交替訪問,鎖升級,升級爲輕量級鎖。
重量級鎖:多個線程訪問,競爭激烈,升級了重量級鎖。
十三、