1.將數組轉化爲列表
將數組轉化爲一個列表時,程序員們經常這樣做:
1
|
List<String>
list = Arrays.asList(arr); |
Arrays.asList()
會返回一個ArrayList對象,ArrayList類是Arrays的一個私有靜態類,而不是java.util.ArrayList類,java.util.Arrays.ArrayList類有set()、get()、contains()方法,但是沒有增加元素的方法,所以它的大小是固定的,想要創建一個真正的ArrayList類,你應該這樣做:
1
|
ArrayList<String>
arrayList = new
ArrayList<String>(Arrays.asList(arr)); |
ArrayList的構造方法可以接受一個集合類型,剛好它也是java.util.Arrays.ArrayList的超類。
2.判斷一個數組是否包含一個值
程序員們經常這樣做:
1
2
|
Set<String>
set = new
HashSet<String>(Arrays.asList(arr)); return
set.contains(targetValue); |
這段代碼起作用,但是沒有必要把一個數組轉化成列表,轉化爲列表需要額外的時間。它可以像下面那樣簡單:
1
|
Arrays.asList(arr).contains(targetValue); |
或者是:
1
2
3
4
5
6
|
for (String
s:arr){ if (s.equals(targetValue)){ return
true ; } } return
false ; |
第一種方法比第二種更容易讀
3.在一個循環中刪除一個列表中的元素
思考下面這一段在循環中刪除多個元素的的代碼
1
2
3
4
5
|
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); |
輸出結果是:
1
|
[b,d] |
在這個方法中有一個嚴重的錯誤。當一個元素被刪除時,列表的大小縮小並且下標變化,所以當你想要在一個循環中用下標刪除多個元素的時候,它並不會正常的生效。
你也許知道在循環中正確的刪除多個元素的方法是使用迭代,並且你知道java中的foreach循環看起來像一個迭代器,但實際上並不是。考慮一下下面的代碼:
1
2
3
4
5
6
|
ArrayList<String>
list = new
ArrayList<String>(Arrays.asList( "a" , "b" , "c" , "d" )); for (String
s:list){ if (s.equals( "a" )){ list.remove(s); } } |
它會拋出一個ConcurrentModificationException異常。
相反下面的顯示正常:
1
2
3
4
5
6
7
8
|
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經常會用到。
HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap
5.在集合中使用原始類型
在Java中原始類型與無界通配符類型很容易混合在一起,拿Set來說,Set是一個原始類型,而Set<?>
是無界的通配符類型。
考慮下面使用原始類型List作爲參數的代碼:
1
2
3
4
5
6
7
|
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 ); |
這段代碼會拋出一個異常:
1
2
|
Exception
in
thread "main"
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at
... |
使用原生類型集合是危險的,這是因爲原生類型集合跳過了泛型類型檢查,並且不是安全的,在Set
、Set<?>
和Set<Object>
中有很大的不同,具體請看Raw
type vs. Unbounded wildcard和Type
Erasure。
6.訪問級別
程序員們經常使用public作爲類字段的修飾符,可以很簡單的通過引用得到值,但這是一個壞的設計,按照經驗,分配給成員變量的訪問級別應該儘可能的低。
public, default, protected, and private
7.ArrayList與LinkedList的對比
當程序員們不知道ArrayList與LinkedList的區別時,他們經常使用ArrayList,因爲它看起來比較熟悉。然而,它們之前有巨大的性能差別。簡而言之,如果有大量的增加刪除操作並且沒有很多的隨機訪問元素的操作,應該首先LinkedList。如果你剛接觸它們,請查看 ArrayList vs. LinkedList來獲得更多關於它們性能的信息。
8.可變與不可變
不可變對象有許多的優點,比如簡單,安全等等。但是對於每一個不同的值都需要一個獨立的對象,太多的對象可能會造成大量的垃圾回收。當選擇可變與不可變時應該有一個平衡。
一般的,可變對象用來避免產生大量的中間對象。一個典型的例子是連接大量的字符串。如果你用一個不可變的字符串,你會產生很多需要進行垃圾回收的對象。這很浪費CPU的時間,使用可變對象是正確的解決方案(比如StringBuilder)。
1
2
3
4
|
String
result= "" ; for (String
s: arr){ result
= result + s; } |
有時在某些情況下也是需要可變對象的,比如將可變對象作爲參數傳入方法,你不用使用很多語句便可以得到多個結果。另外一個例子是排序和過濾:當然,你可以寫一個方法來接收原始的集合,並且返回一個排好序的集合,但是那樣對於大的集合就太浪費了。(來自StackOverFlow的dasblinkenlight’s的答案)
9.父類與子類的構造函數
這個編譯期錯誤的出現是父類默認的構造方法未定義,在java中,如果一個類沒有定義構造方法,編譯器會默認的爲這個類添加一個無參的構造方法。如果在父類中定義了構造方法,在這個例子中是Super(String s),編譯器就不會添加默認的無參構造方法,這就是上面這個父類的情形。
子類的構造器,不管是無參還有有參,都會調用父類的無參構造器。因爲編譯器試圖在子類的兩個構造方法中添加super()方法。但是父類默認的構造方法未定義,編譯器就會報出這個錯誤信息。
想要修復這個問題,可以簡單的通過1)在父類中添加一個Super()構造方法,像下面這樣:
1
2
3
|
public
Super(){ System.out.println( "Super" ); } |
或者2)移除父類自定義的構造方法,或者3)在子類的構造方法中調用父類的super(value)方法。
10.”"還是構造器
有兩種方式可以創建字符串
1
2
3
4
|
//1.使用字符串 String
x = "abc" ; //2.使用構造器 String
y = new
String( "abc" ); |
有什麼區別?
下面的例子會給出一個快速的答案:
1
2
3
4
5
6
7
8
9
|
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 |
關於它們內存分配的更多信息,請參考Create Java String Using ” ” or Constructor?.
將來的工作
這個列表是我基於大量的github上的開源項目,Stack overflow上的問題,還有一些流行的google搜索的分析。沒有明顯示的評估證明它們是前10,但它們絕對是很常見的。如果您不同意任一部分,請留下您的評論。如果您能提出其它一些常見的錯誤,我將會非常感激。
原文鏈接: programcreek 翻譯: ImportNew.com - 林林譯文鏈接: http://www.importnew.com/12074.html
[ 轉載請保留原文出處、譯者和譯文鏈接。]