有些東西,當你即將失去了的時候,你才懂得它的彌足珍貴,也許亡羊補牢,爲時未晚!html
建議67:不一樣的列表選擇不一樣的遍歷算法算法
建議68:頻繁插入和刪除時使用LinkedList數組
建議69:列表相等只關心元素數據緩存
建議70:子列表只是原列表的一個視圖安全
建議71:推薦使用subList處理局部列表多線程
建議72:生成子列表後不要再操做原列表性能
建議73:使用Comparator進行排序測試
建議74:不推薦使用binarySearch對列表進行檢索大數據
建議75:集合中的元素必須作到compareTo和equals同步加密
建議76:集合運算的並集、交集、差集
建議77:使用shuffle打亂列表
建議78:減小hashmap中元素的數量
建議79:集合中哈希碼不要重複
建議80:多線程使用Vector或HashTable
建議81:非穩定排序推薦使用List
建議82:由點及面,集合你們族總結
建議67:不一樣的列表選擇不一樣的遍歷算法
測試來看簡單for循環比foreach能快那麼一丟丟。
建議68:頻繁插入和刪除時使用LinkedList
ArrayList在進行插入元素時:
public void add(int index, E element) { //檢查下標是否越界 rangeCheckForAdd(index); //若須要擴容,則增大底層數組的長度 ensureCapacityInternal(size + 1); // Increments modCount!! //給index下標以後的元素(包括當前元素)的下標加1,空出index位置 System.arraycopy(elementData, index, elementData, index + 1,size - index); //賦值index位置元素 elementData[index] = element; //列表長度加1 size++; }
注意看arrayCopy方法,只要插入一個元素,其後的元素就會向後移動一位,雖然arrayCopy是一個本地方法,效率很是高,但頻繁的插入,每次後面的元素都要拷貝一遍,效率變的就低了。而使用LinkedList就顯得更好了,LinkedList是一個雙向列表,它的插入只是修改了相鄰元素的next和previous引用。
原理不說了。
修改元素:LinkedList不如ArrayList,由於LinkedList是按順序存儲的,所以定位元素必然是一個遍歷過程,效率大打折扣。而ArrayList的修改動做是數組元素的直接替換,簡單高效。
LinkedList:刪除和插入效率高;ArrayList:修改元素效率高。
建議69:列表相等只關心元素數據
判斷集合是否相等只須關注元素是否相等便可,不用看容器
建議70:子列表只是原列表的一個視圖
List接口提供了subList方法,其做用是返回一個列表的子列表,這與String類subSting有點相似。
注意:subList產生的列表只是一個視圖,全部的修改動做直接做用於原列表。
建議71:推薦使用subList處理局部列表
咱們來看這樣一個簡單的需求:一個列表有100個元素,如今要刪除索引位置爲20~30的元素。這很簡單,一個遍歷很快就能夠完成,代碼以下:
public class Client71 { public static void main(String[] args) { // 初始化一個固定長度,不可變列表 List<Integer> initData = Collections.nCopies(100, 0); // 轉換爲可變列表 List<Integer> list = new ArrayList<Integer>(initData); // 遍歷,刪除符合條件的元素 for (int i = 0; i < list.size(); i++) { if (i >= 20 && i < 30) { list.remove(i); } } } }
這段代碼很符合個人風格!
下面用subList解決這個問題:
public static void main(String[] args) { // 初始化一個固定長度,不可變列表 List<Integer> initData = Collections.nCopies(100, 0); // 轉換爲可變列表 List<Integer> list = new ArrayList<Integer>(initData); //刪除指定範圍內的元素 list.subList(20, 30).clear(); }
建議72:生成子列表後不要再操做原列表
注意:subList生成子列表後,保持原列表的只讀狀態。
建議73:使用Comparator進行排序
一、默認排序
Collections.sort(list)
二、按某字段排序
Collections.sort(list,new PositionComparator())
知道這些就好了,原文寫的太晦澀了,我感受沒啥用!
想了解更多的使用Comparator進行排序
建議74:不推薦使用binarySearch對列表進行檢索
不推薦,乾脆就不要寫了,好嗎?
對列表進行檢索就使用indexOf就挺好的!
public class Client74 { public static void main(String[] args) { List<String> cities = new ArrayList<String> (); cities.add("上海"); cities.add("廣州"); cities.add("廣州"); cities.add("北京"); cities.add("天津"); //indexOf取得索引值 int index1= cities.indexOf("廣州"); //binarySearch找到索引值 int index2= Collections.binarySearch(cities, "廣州"); System.out.println("索引值(indexOf):"+index1); System.out.println("索引值(binarySearch):"+index2); } }
binarySearch採用的是二分法搜索的Java版實現。從中間開始搜索,結果確定是2了。
使用binarySearch的二分法查找比indexOf的遍歷算法性能上高不少,特別是在大數據集且目標值又接近尾部時,binarySearch方法與indexOf方法相比,性能上會提高几十倍,所以從性能的角度考慮時能夠選擇binarySearch。
建議75:集合中的元素必須作到compareTo和equals同步
一看到標題,短期有些發懵,簡單來講,
indexOf依賴equals方法查找,binarySearch則依賴compareTo方法查找;
equals是判斷元素是否相等,compareTo是判斷元素在排序中的位置是否相同。
注意:實現了compareTo方法就應該覆寫equals方法,確保二者同步。
建議76:集合運算的並集、交集、差集
一、並集 addAll
二、交集 retainAll
三、差集 removeAll
四、無重複的並集
並集是集合A加集合B,那若是集合A和集合B有交集,就須要確保並集的結果中只有一份交集,此爲無重複的並集,此操做也比較簡單,代碼以下:
//刪除在list1中出現的元素 list2.removeAll(list1); //把剩餘的list2元素加到list1中 list1.addAll(list2);
之因此介紹並集、交集、差集,那是由於在實際開發中,不多有使用JDK提供的方法實現集合這些操做,基本上都是採用了標準的嵌套for循環:要並集就是加法,要交集就是contains判斷是否存在,要差集就使用了!contains(不包含)。
之因此會寫這麼low的東西是想告誡本身多用JDK提供的方法,不要總想着本身去實現,不少東西Java老賊都有現成的!
建議77:使用shuffle打亂列表
簡而言之,言而總之,shuffle就是用來打亂list列表順序的,應用的場景好比
一、在抽獎程序中:好比年會的抽獎程序,先使用shuffle把員工順序打亂,每一個員工的中獎概率相等,而後就能夠抽出第一名、第二名。
二、用於安全傳輸方法:好比發送端發送一組數據,先隨機打亂順序,而後加密發送,接收端解密,而後進行排序!
建議78:減小hashmap中元素的數量
一、hashmap和ArrayList的長度都是動態增長的,兩者機制有些不一樣
二、先說hashmap,它在底層是以數組的方式保存元素的,其中每個鍵值對就是一個元素,也就是說hashmap把鍵值對封裝成一個entry對象,而後再將entry對象放到數組中,也就是說hashmap比ArrayList多一層封裝,多出一倍的對象。
在插入鍵值對時會作長度校驗,若是大於或者等於閾值,則數組長度會增大一倍。
hashMap的size大於數組的0.75倍時,就開始擴容,一次擴容兩倍。
三、ArrayList的擴容策略,它是在小於數組長度的時候纔會擴容1.5倍。
綜合來講,HashMap比ArrayList多了一層Entry的底層封裝對象,多佔用了內存,而且它的擴容策略是2倍長度的遞增,同時還會根據閾值判斷規則進行判斷,所以相對於ArrayList來講,一樣的數據,它就會優先內存溢出。
注:Entry是Map中用來保存一個鍵值對的,而Map實際上就是多個Entry的集合。
建議79:集合中哈希碼不要重複
一、Java中hashcode的理解
JVM每new一個Object,都會在Hash哈希表中產生一個hashcode。假設不一樣的對象產生了相同的hashcode,hash key相同致使衝突,那麼就在這個hash key的地方產生了一個鏈表,將一樣hashcode的對象放到單鏈表中,串到一塊兒。
重寫equals時必定要重寫hashcode方法
兩個相等對象的equals方法必定爲true, 但兩個hashcode相等的對象不必定是相等的對象。
hashcode相等僅僅保證兩個對象在hash表裏的同一個hash鏈上,繼而經過equals方法才能肯定是否是同一個對象。
總而言之,hashmap中hashcode應避免衝突。
建議80:多線程使用Vector或HashTable
Vector是ArrayList的多線程版本,HashTable是HashMap的多線程版本。
建議81:非穩定排序推薦使用List
什麼叫非穩定排序?
public static void main(String[] args) { SortedSet<Person> set = new TreeSet<Person>(); // 身高180CM set.add(new Person(180)); // 身高175CM set.add(new Person(175)); set.first().setHeight(185); for (Person p : set) { System.out.println("身高:" + p.getHeight()); } }
奇了怪了,爲何呢?這個就是非穩定排序。
SortedSet接口(TreeSet實現了此接口)只是定義了在給集合加入元素時將其進行排序,並不能保證元素修改後的排序結果,所以TreeSet適用於不變量的集合數據排序。
解決方法:
一、Set集合重排序:從新生成一個Set對象,再排序。
set.first().setHeight(185); //set重排序 set=new TreeSet<Person>(new ArrayList<Person>(set));
感受若是這麼寫就失去了代碼了樂趣了,太愚蠢了,pass。
二、使用List解決
使用Collections.sort()方法對List排序。
list中容許有重複的元素,避免重複能夠先轉成HashSet,去重後再轉回來。
建議82:由點及面,集合你們族總結
Java中的集合類實在是太豐富了,有經常使用的ArrayList、HashMap,也有不經常使用的Stack、Queue,有線程安全的Vector、HashTable,也有線程不安全的LinkedList、TreeMap,有阻塞式的ArrayBlockingQueue,也有非阻塞式的PriorityQueue等,整個集合你們族很是龐大,能夠劃分如下幾類:
一、List:
實現List接口的集合主要有:ArrayList、LinkedList、Vector、Stack,其中ArrayList是一個動態數組,LinkedList是一個雙向鏈表,Vector是一個線程安全的動態數組,Stack是一個對象棧,遵循先進後出的原則。
stack簡介:
Stack來自於Vector,那麼顯然stack的底層實現是數組。
stack的方法:
① push(xx); //入棧
② pop() ; //棧頂元素出棧
③ empty() ; //斷定棧是否爲空
④ peek(); //獲取棧頂元素
⑤ search(xx); //判端元素num是否在棧中,若是在返回1,不在返回-1。
二、Set:
Set是不包含重複元素的集合,其主要實現類有:EnumSet、HashSet、TreeSet,其中EnumSet是枚舉類型專用Set,全部元素都是枚舉類型;HashSet是以哈希嗎決定其元素位置的Set,其原理和hashmap類似,它提供快速的插入和查找方法;TreeSet是一個自動排序的Set,它實現了SortedSet接口。
三、Map:
HashMap、HashTable、Properties、EnumMap、TreeMap等。
其中properties是hashtable的子類,它的主要用途是從property文件中加載數據,並提供方便的操做,EnumMap則要求其key必須是一個枚舉類型。
map中還有一個WeakHashMap類須要簡單說明一下,它是一個採用弱鍵方式的map類,它的特色是:WeakHashMap對象的存在並不會阻止垃圾回收器對鍵值對的回收,也就是說使用WeakHashMap不用擔憂內存溢出的問題,GC會自動刪除不用的鍵值對,但存在一個嚴重的問題:GC是靜悄悄的回收的(什麼時候回收,God,Knows!)咱們的程序沒法知曉該動做,存在着重大的隱患。
WeakHashMap存在重大隱患,那這個東西何時使用呢?
在《Effective Java》一書中第六條,消除陳舊對象時,提到了weakHashMap,使用短期內就過時的緩存時最好使用weakHashMap。
四、Queue:
五、數組:
數組與集合的最大區別是數組可以容納基本類型,而集合只能容納引用類型,全部的集合底層存儲的都是數組。