一般開發者轉化數組爲ArrayList的方式爲java
List<String> list = Arrays.asList(arr);
Arrays.asList()會返回一個ArrayList,而這個ArrayList是Arrays類的靜態內部類,不是java.util.ArrayList。數組
這個類有get()、set()和contains()方法,但卻沒有任何能夠添加元素的方法。正確的作法能夠這樣作安全
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));
部分開發者會這樣實現數據結構
return new HashSet<String>(Arrays.asList(arr)).contains(targetValue);
結果是對的,可是沒有必要轉化爲Set,這反而會花費更多時間,能夠簡單這樣實現函數
return Arrays.asList(arr).contains(targetValue);
或者性能
for(String s: arr){ if(s.equals(targetValue)) return true; } return false;
補充:第一種相比第二種可讀性會高一些。ui
分析一下下列代碼:this
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]
設計
由於當數組刪除一個元素後,它的長會縮小,index至關於向後移動一位,這是個嚴重的問題。當你想經過index來刪除多個元素時候,這種方法是不可取的。
你也許知道用迭代器來刪除是沒問題的,而且java中有一類for語句原理就是使用迭代器。但實際你想用這類for語句來代替迭代器進行刪除也是不行的,以下代碼
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()以前被調用。而在for循環中,編譯器會在元素被remove以後調用next(),所以就會拋出ConcurrentModificationException異常。
java中有兩類,HashTable和HashMap,二者的數據結構是一致的(哈希表),而後二者的區別是:HashTable是同步的。
因此HashTable是線程安全的,HashMap不是線程安全的。
提示:也可使用ConcurrentHashMap來保證線程安全,ConcurrentHashMap使用分段鎖(segment)的原理,效率上會高一些。
在java中,開發者一般把原生態類型(raw type)一般和無界通配符類型(unbounded wildcard type)弄混。拿Set來舉例子,Set是原生態類型,而Set<?>是無界通配符類型。
以下代碼使用了原生態類型
public static void add(List list, Object o){ list.add(o); } public 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 ...
原生態類型會越過泛型的校驗,是不安全的。
有的開發者將類某些屬性直接定義爲public,這很容易經過外部訪問,但絕對是不好的設計。根據拇指規則,最佳作法應該是儘可能減小屬性的訪問級別。
不少開發者都習慣使用ArrayList,可能ArrayList相對來講比較熟悉的緣故,其實ArrayList和LinkList仍是存在很大的區別。簡而言之,LinkList應該在有大量增刪操做且無隨機訪問操做時候使用。
不可變對象有不少優勢,好比簡單、安全等。但對於多個值則須要多個不一樣的對象來表示,對象過多時,會消耗不少的GC資源。
一般的,可變對象可用來避免產生過多的對象。以下代碼中使用了不可變對象,那麼執行過程當中將會產生不少的String,消耗不少時間和cpu性能。若是換成可變對象(StringBuilder等),將會好不少。
String result=""; for(String s: arr){ result = result + s; }
class Super { String s; public Super(String s) { super(); this.s = s; } } class Sub extends Super { public Sub(String s) { } public Sub() { } }
上述代碼會出錯,是由於父類默認構造函數沒有定義。在java中,若是一個類沒有定義構造函數,則編譯器會給它構造默認的無參構造函數。若是類中定義了構造函數,那麼編譯器將不會給它插入默認構造函數。這個正是上述父類的遇到的狀況。
在子類中的兩個構造函數中,編譯器試圖插入父類的默認構造函數super();
,然而並未找到,所以編譯出錯。
字符串能夠經過兩種方式創建
//1. 直接引用 String x = "abc"; //2. 使用構造函數 String y = new String("abc");
二者卻別可經過以下代碼闡明
String a = "abcd"; String b = "abcd"; System.out.println(a == b); // True System.out.println(a.equals(b)); // True String c = new String("abcd"); String d = new String("abcd"); System.out.println(c == d); // False System.out.println(c.equals(d)); // True