內嵌,J2SE常用類,Comparator 和 Comparable
內嵌
當一個final函式被呼叫通常Java編譯器可以通過呼叫方法的編譯程式碼直接內嵌來備份子程式的位元組碼,這是什麼意思?
1.首先要明白一點,呼叫一個函式除了函式本身的執行時間之外,還需要額外的時間去尋找這個函式(類內部有一個函式簽名和函式地址的對映表)。所以減少函式呼叫次數就等於降低了效能消耗。
2.final修飾的函式會被編譯器優化,優化的結果是減少了函式呼叫的次數。編譯器是如何實現的呢?舉個例子:
public class Test { final void func(){System.out.println("g");} public void main(String[] args) { for(int j=0;j<1000;j++) func(); } }
//經過編譯器優化之後,這個類變成了相當於這樣寫:
public class Test
{
final void func(){System.out.println("g");};
public void main(String[] args)
{
for(int j=0;j<1000;j++)
{System.out.println("g");};
}
}
編譯器直接將func的函式體內嵌到了呼叫函式的地方,這樣的結果是節省了1000次函式呼叫。當然編譯器處理成位元組碼,我那樣寫是為了讓你看明白。不過,當函式體太長的話,用final可能適得其反,因為經過編譯器內嵌之後程式碼長度大大增加,於是就增加了jvm解釋位元組碼的時間。
當編譯器發現一個final 方法呼叫命令時,它會根據自己的謹慎判斷,跳過插入程式程式碼這種正常方式而執行方法呼叫機制(將引數壓入棧,跳至方法程式碼處並執行,然後跳回並清理棧中的引數,處理返回值),並且以方法體中的實際程式碼的複本來替代方法呼叫。這將消除方法呼叫的開銷。
當然,如果一個方法很大,你的程式程式碼就會膨脹,因而可能看不到內嵌帶來的任何效能的提高。
因為,所帶來的效能提高會因為花費於方法內的時間量而被縮減。
這意味著java編譯器能夠觀察到這些情況並明智地抉擇是否對final方法執行內嵌動作。
然而,最好是讓編譯器和JVM僅在你明確表示要阻止覆蓋時,再處理效率問題,並將方法指明為final。
在1.5後的版本中,虛擬機器可以探測到這些情況,並優化去掉這些效率反而降低的額外的內鑲呼叫,因此不再需要使用final方法來進行優化了。只用要明確禁止覆蓋是才將方法設定為final的。
=========================================================
Java SE常用類總結
【基本資料包裝類】
Integer :基本資料int包裝類Character :基本資料char包裝類
Long:基本資料long的包裝類
Short:基本資料short包裝類
Byte:基本資料byte包裝類
Double:基本資料double的包裝類
Float:基本資料float的包裝類
Boolean:基本資料boolean的包裝類、
【字串操作類】
String 字串類
StringBuilder,StringBuffer 字串緩衝區
【陣列工具類】
Arrays 陣列工具類
【集合】
Collection(介面):集合的父級介面
List(介面),Set(介面) :Collection 中的常用的子介面
ArrayList,LinkedList,Vector :由List介面衍生的集合類
HashSet,TreeSet,LinkedHashSet :由Set介面衍生的集合類
Itetator(介面):迭代器
Iterable(介面):實現這個介面允許物件成為 "foreach" 語句的目標。俗話:可以使用增強for迴圈
Collcetions 集合工具類
Map(介面):鍵值對集合介面
HashMap :底層資料結構hash表
TreeMap :底層資料結構二叉樹
HashTable :底層資料結構為hash表
LinkedHashMap :可以記住存入該集合鍵值對的內容
Properties :操作配置檔案
【IO流】
InputStream(抽象類),OutputStream(抽象類)
FileInputStream,FileoutStream, BufferedInputStream ,BufferedOutputStream
Reader(抽象類),Writer(抽象類)
FileReader,FileWriter,BufferedReader,BufferedWriter,
InoutStreamReader , OutputStreamWriter :轉換流
PrintStream , SequenceInputStream , 列印流 序列化流
ObjectInputStream , ObjectOutputStream物件的序列化流--- Serializable(介面)
ByteArrayInputStream , ByteArrayOutputStream 記憶體操作流
PipedInputStream , PipedOutputStream 管道流
DataInputStream , DataOutputSteam 基本資料型別操作流
RandomAccessFile 隨機讀寫流
【檔案】
File:對檔案進行包裝,操作的類
【多執行緒】
Thread :
Runable(介面)
Condition(介面)
【時間/日期】
Date :
Format(抽象類) SimpleDataFormat
Calendar :
【GUI圖形化介面】
Frame , Panel ,TextArea ,Button ,TextFiled
BorderLayout ,FlowLaout ,
WindowListener , WindowAdapter ,WindowEvent ,
ActionListener(介面) , ActionEvent
KeyAdapter ,
【網路程式設計】
DatagramSocket ,DatagramPacket:UDP協議
Socket ,SeverSocket :TCP協議
【正則表示式】
Pattern :
Matcher :
【反射】
Class:位元組碼檔案的基類
Constructor:建構函式類
Method:成員方法類
Field:成員變數
=========================================================
Comparator 和 Comparable
comparable&comparator 都是用來實現集合中的排序的,只是Comparable是在集合內部定義的方法實現的排序,Comparator是在集合外部實現的排序,所以,如想實現排序,就需要在集合外定義Comparator介面的方法compare()或在集合內實現Comparable介面的方法compareTo()。
Comparable是一個物件本身就已經支援自比較所需要實現的介面(如String Integer自己就可以完成比較大小操作)。
Comparator是一個專用的比較器,當這個物件不支援自比較或者自比較函式不能滿足你的要求時,你可以寫一個比較器來完成兩個物件之間大小的比較。
當需要排序的集合或陣列不是單純的數字型時,通常可以使用Comparator或Comparable,以簡單的方式實現物件排序或自定義排序。
一、Comparator,強行對某個物件collection進行整體排序的比較函式,可以將Comparator傳遞給Collections.sort或Arrays.sort。
二、Comparable,強行對實現它的每個類的物件進行整體排序,實現此介面的物件列表(和陣列)可以通過Collections.sort或Arrays.sort進行自動排序。
可以說一個是自己完成比較,一個是外部程式實現比較的差別而已。
用 Comparator 是策略模式(strategy design pattern),就是不改變物件自身,而用一個策略物件(strategy object)來改變它的行為。
比如:你想對整數採用絕對值大小來排序,Integer 是不符合要求的,你不需要去修改 Integer 類(實際上你也不能這麼做)去改變它的排序行為,只要使用一個實現了 Comparator 介面的物件來實現控制它的排序就行了。
Comparator 在java.util包中
Comparable 在java.lang包中
Comparator 和 Comparable 的例項
//Comparable:
//實現Comparable介面要覆蓋compareTo方法, 在compareTo方法裡面實現比較:
public class Person implements Comparable {
String name;
int age
public int compareTo(Person another) {
int i = 0;
i = name.compareTo(another.name); // 使用字串的比較
if(i == 0) { // 如果名字一樣,比較年齡, 返回比較年齡結果
return age - another.age;
} else {
return i; // 名字不一樣, 返回比較名字的結果.
}
}
}
// 這時我們可以直接用 Collections.sort( personList ) 對其排序了.
//Comparator:
//實現Comparator需要覆蓋 compare 方法:
public class Person{
String name;
int age
}
class PersonComparator implements Comparator {
public int compare(Person one, Person another) {
int i = 0;
i = one.name.compareTo(another.name); // 使用字串的比較
if(i == 0) { // 如果名字一樣,比較年齡,返回比較年齡結果
return one.age - another.age;
} else {
return i; // 名字不一樣, 返回比較名字的結果.
}
}
}
// Collections.sort( personList , new PersonComparator()) 可以對其排序
總結:
兩種方法各有優劣, 用Comparable 簡單, 只要實現Comparable 介面的物件直接就成為一個可以比較的物件,但是需要修改原始碼, 用Comparator 的好處是不需要修改原始碼, 而是另外實現一個比較器, 當某個自定義的物件需要作比較的時候,把比較器和物件一起傳遞過去就可以比大小了, 並且在Comparator 裡面使用者可以自己實現複雜的可以通用的邏輯,使其可以匹配一些比較簡單的物件,那樣就可以節省很多重複勞動了。