轉自CSDN:
1.將陣列轉化為列表
將陣列轉化為一個列表時,程式設計師們經常這樣做:
List<String> list = Arrays.asList(arr);
Arrays.asList()
會返回一個ArrayList物件,ArrayList類是Arrays的一個私有靜態類,而不是java.util.ArrayList類,java.util.Arrays.ArrayList類有set()、get()、contains()方法,但是沒有增加元素的方法,所以它的大小是固定的,想要建立一個真正的ArrayList類,你應該這樣做:
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));
ArrayList的構造方法可以接受一個集合型別,剛好它也是java.util.Arrays.ArrayList的超類。
2.判斷一個陣列是否包含一個值
程式設計師們經常這樣做:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
這段程式碼起作用,但是沒有必要把一個陣列轉化成列表,轉化為列表需要額外的時間。它可以像下面那樣簡單:
Arrays.asList(arr).contains(targetValue);
或者是:
for(String s:arr){
if(s.equals(targetValue)){
return true;
}
}
return false;
第一種方法比第二種更容易讀
3.在一個迴圈中刪除一個列表中的元素
思考下面這一段在迴圈中刪除多個元素的的程式碼
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));
for(int i=0;i<list.size();i++){
list.remove(i);
}
System.out.println(list);
輸出結果是:
[b,d]
在這個方法中有一個嚴重的錯誤。當一個元素被刪除時,列表的大小縮小並且下標變化,所以當你想要在一個迴圈中用下標刪除多個元素的時候,它並不會正常的生效。
你也許知道在迴圈中正確的刪除多個元素的方法是使用迭代,並且你知道java中的foreach迴圈看起來像一個迭代器,但實際上並不是。考慮一下下面的程式碼:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));
for(String s:list){
if(s.equals("a")){
list.remove(s);
}
}
它會丟擲一個ConcurrentModificationException異常。
相反下面的顯示正常:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));
Iterator<String> iter = list.iterator();
while(iter.hasNext()){
String s = iter.next();
if(s.equals("a")){
iter.remove();
}
}
.next()
必須在.remove()
之前呼叫。在一個foreach迴圈中,編譯器會使.next()在刪除元素之後被呼叫,因此就會丟擲ConcurrentModificationException異常,你也許希望看一下ArrayList.iterator()的原始碼。
4.Hashtable與HashMap的對比
就演算法而言,雜湊表是資料結構的一個名字。但是在java中,這個資料結構的名字是HashMap。Hashtable與HashMap的一個重要不同點是Hashtable是同步的。所以你經常不需要Hashtable,相反HashMap經常會用到。
5.在集合中使用原始型別
在Java中原始型別與無界萬用字元型別很容易混合在一起,拿Set來說,Set是一個原始型別,而Set<?>
是無界的萬用字元型別。 考慮下面使用原始型別List作為引數的程式碼:
public static void add(List list,Object o){
list.add(o);
}
pulbic static void main(String[] args){
List<String> list = new ArrayList<String>();
add(list,10);
String s = list.get(0);
這段程式碼會丟擲一個異常:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at ...
使用原生型別集合是危險的,這是因為原生型別集合跳過了泛型型別檢查,並且不是安全的,在Set
、Set<?>
和Set<Object>
中有很大的不同。
6.訪問級別
程式設計師們經常使用public作為類欄位的修飾符,可以很簡單的通過引用得到值,但這是一個壞的設計,按照經驗,分配給成員變數的訪問級別應該儘可能的低。
7.ArrayList與LinkedList的對比
當程式設計師們不知道ArrayList與LinkedList的區別時,他們經常使用ArrayList,因為它看起來比較熟悉。然而,它們之前有巨大的效能差別。簡而言之,如果有大量的增加刪除操作並且沒有很多的隨機訪問元素的操作,應該首先LinkedList。
8.可變與不可變
不可變物件有許多的優點,比如簡單,安全等等。但是對於每一個不同的值都需要一個獨立的物件,太多的物件可能會造成大量的垃圾回收。當選擇可變與不可變時應該有一個平衡。 一般的,可變物件用來避免產生大量的中間物件。一個典型的例子是連線大量的字串。如果你用一個不可變的字串,你會產生很多需要進行垃圾回收的物件。這很浪費CPU的時間,使用可變物件是正確的解決方案(比如StringBuilder)。
String result="";
for(String s: arr){
result = result + s;
}
有時在某些情況下也是需要可變物件的,比如將可變物件作為引數傳入方法,你不用使用很多語句便可以得到多個結果。另外一個例子是排序和過濾:當然,你可以寫一個方法來接收原始的集合,並且返回一個排好序的集合,但是那樣對於大的集合就太浪費了。
9.父類與子類的建構函式
這個編譯期錯誤的出現是父類預設的構造方法未定義,在java中,如果一個類沒有定義構造方法,編譯器會預設的為這個類新增一個無參的構造方法。如果在父類中定義了構造方法,在這個例子中是Super(String s),編譯器就不會新增預設的無參構造方法,這就是上面這個父類的情形。 子類的構造器,不管是無參還有有參,都會呼叫父類的無參構造器。因為編譯器試圖在子類的兩個構造方法中新增super()方法。但是父類預設的構造方法未定義,編譯器就會報出這個錯誤資訊。 想要修復這個問題,可以簡單的通過1)在父類中新增一個Super()構造方法,像下面這樣:
public Super(){
System.out.println("Super");
}
或者2)移除父類自定義的構造方法,或者3)在子類的構造方法中呼叫父類的super(value)方法。
10.”"還是構造器
有兩種方式可以建立字串
//1.使用字串
String x = "abc";
//2.使用構造器
String y = new String("abc");
有什麼區別?
下面的例子會給出一個快速的答案:
String a = "abc";
String b = "abc";
System.out.println(a==b);//true
System.out.println(a.equals(b));//true
String c = new String("abc");
String d = new String("abc");
System.out.println(c==d);//false
System.out.println(c.equals(d));//true
原文:https://cloud.tencent.com/developer/article/1006743