我們到底能走多遠系列(15)
扯淡:這些知識點來源是通過面試涉及到的,面的公司不多,知識點涉及也不多,我每次面試後都在備忘錄裡寫下有用的東西,集合起來分享一下,因為是知識點,所以就不出什麼面試題目啦。不涉及任何公司,也不談論面經,純粹是學習而已。
《我們到底能走多遠系列》的階段性目標已經達到啦,15個,先給自己鼓勵一下吧。
有目的性學習的確會讓人不偷懶,能讓人在短時間裡努力,自我激勵的方式很多,每天花點時間做一件事對你肯定有協助,好吧先講一個故事,口癢了,哈哈。
可能很多朋友都聽過了,沒關係,再聽一遍,你就可以熟練的講給你的朋友們聽了。
從前有兩個和尚他們分別住在河對岸的兩個廟裡,每天他們都會來河邊打水,每天都會見面,時間一長他們就相當於那啥,心靈相通,成了好朋友,但他們誰也沒跨過河去看望過對方。這樣年複一年,一日,住在東岸的和尚沒來打水,西岸的和尚就疑惑了,一天不打水,他喝什麼呢?第二天,西岸的和尚還是沒來,連續半個月東岸的和尚都沒見到西岸的和尚,於是他就想他朋友是不是病了。於是就挑著水去到西岸的廟裡,他看到他的朋友一點沒事,就問他:你怎麼不來河裡打水了呢,沒有水,你喝什麼呢?西岸的和尚把他朋友領到園子裡,指著角落裡的一口井說,這是我挖的一口井,有了井,就不用再去河邊打水了。東岸的和尚又問了:我們平時在廟裡怎麼忙,幾乎沒有閒置時間,你怎麼可能有時間挖一口井呢?回答:我每天就在那個地方掘一下,年複一年,它就成了井。
你在掘你的井嗎?
主題:
關於資料結構:有不正確的地方或改進的地方希望你能指出來,我會感謝你給我進步的機會。
1,stack
來自《Introduction to Algorithms》的圖:
遵循先進後出(FILO)的原則,下面是類比的代碼:
package code.structures;public class Stack { private String[] s;// 用數組來類比 private int top; private int length; // 初始化 public Stack(int index){ this.s = new String[index]; this.top = 0; this.length = index; } // 放資料 public void push(String str){ if(str == null){ return; } if(top == length){ System.out.println("stack is full"); return; } this.s[top] = str; this.top++; } // 拿資料 public String pop(){ if(this.isEmpty()){ System.out.println("There is no data"); return null; } String s1 = s[--top];//因為數組從0開始,順便每pop一次要把top減一 s[top] = null; return s1; } // 取得最高位置 public int getTop(){ return this.top; } public boolean isEmpty(){ if(this.top == 0){ return true; } return false; }}
2,Query
來自《Introduction to Algorithms》的圖:
遵循先進先出(FIFO)的原則,下面是類比的代碼:
代碼使用標誌符的方式來控制內部的數組不溢出和為空白是不能取出資料。
package code.structures;public class Queue { private String[] s;// 用數組來類比 private int head; // 隊列頭 private int tail; // 隊列尾 private int length; // 隊列長度 private boolean isFull; // 滿訊號 private boolean isEmpty; // 空訊號 public Queue(int index) { this.s = new String[index]; this.head = 0; this.tail = 0; length = index; isFull = false; isEmpty = true; } // 放資料 public boolean enQueue(String str) { if (isFull) { // 已滿的隊列就不能再放資料啦 System.out.println("Query is full"); return false; } // 放在隊列的尾部 s[tail] = str; tail++; // 移動尾部 // 頭尾相連 if (tail == length) { tail = 0; } // 在放資料的時候出現頭尾相同時,就認為是滿了 if (head == tail) { isFull = true; } // 因為是放資料,所以不可能出現空隊列 if (isEmpty) { isEmpty = false; } return true; } // 拿資料 public String deQueue() { if (isEmpty) {// 空隊列就不處理了 System.out.println("Query is empty"); return null; } // 從頭部取得資料 String str = s[head]; head++; if (head == length) { head = 0; } // 取資料的時候出現頭尾相同,就認為出現空隊列 if (head == tail) { isEmpty = true; } // 因為是取資料,所以不可能出現一個滿隊列 if (isFull) { isFull = false; } return str; } public boolean isEmpty(){ return isEmpty; } public boolean isFull(){ return isFull; }}
3,ArrayList和LinkedList
我們不看他們的源碼,但也有必要知道他們大概的實現方式:ArrayList是實現了基於動態數組的資料結構,LinkedList基於鏈表的資料結構。這就是他們區別的關鍵之處,我想著相當於是一個數組和一個鏈表在比較。
ArrayList基於數組的,看他的構造方法:
public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity // 傳入ArrayList大小,就幫你建立一個這樣大小的Object數組 this.elementData = (E[])new Object[initialCapacity]; } public ArrayList() { this(10);//預設的話,就是10大小的數組 }
關於ArrayList的動態數組的實現,是依靠啦一個方法: System.arraycopy方法。
看下面兩個源碼方法就會明白:
public void ensureCapacity(int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { Object oldData[] = elementData; // 新數組長度是老數組的1.5倍 int newCapacity = (oldCapacity * 3)/2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // 建立出新的數組 elementData = (E[])new Object[newCapacity]; // 把老資料拷貝到新數組裡去 System.arraycopy(oldData, 0, elementData, 0, size); } } public boolean add(E o) { ensureCapacity(size + 1); // 確定是否需要增長數組 elementData[size++] = o; return true; }
ArrayList的remove方法,決定了它暴露了頻繁刪除資料效能不高的原因:
public E remove(int index) { RangeCheck(index); modCount++; E oldValue = elementData[index];//刪除的資料作為傳回值 int numMoved = size - index - 1; if (numMoved > 0) // 用一個自我拷貝,移動了刪除點後的全部資料,所以會影響效率 System.arraycopy(elementData, index+1, elementData, index, numMoved); // copy資料後,最後一位的資料還在,需要把它刪除 elementData[--size] = null; // Let gc do its work return oldValue; }
而LinkedList是基於列表的,它的remove只需要斷開一個串連,連上一個串連,無論我們刪除那一個資料需要的時間是相同的。但是考慮到LinkedList的檢索需要更多的時間因為,最差的結果裡,需啊喲遍曆整個Link。
所以:
1.對於隨機訪問get和set,ArrayList覺得優於LinkedList。
2.對於新增和刪除操作add和remove,LinedList比較佔優勢。
3.若只對單條資料插入或刪除,ArrayList的速度反而優於 LinkedList。但若是批量隨機的插入刪除資料,LinkedList的速度大大優於ArrayList.
3.HashMap和HashTable
1.HashMap 線程非安全 null可為key
2.HashTable 安全執行緒 null不可為key
3.HashTable有一個contains(Object value),功能和containsValue(Object value)功能一樣。
4.SQL基礎幾點
1,case語句的使用
select classId, count(case when sex = "男" then 1 end) from Test group by classTd;
2,group by :
select後面的所有列中,沒有使用彙總函式的列,必須使用group by!
3,having:
篩選滿足條件的組,條件經常包含彙總組函數.
4,left join 相當於 left out join ,right join 相當於 right out join 也就是說什麼外串連就是左串連和右串連嘛(不知道準不準確),join 相當於 inner join。
還有個full join,鏈表全部需要查出來嘛。
left join和right join相當於是求有交集的兩個集合的一個集合的值。
inner join相當於是純粹的交集。
full join 你懂的還剩下並集。
5,代碼規範
可讀性:代碼是否可讀易讀,對於一個團隊來說,編碼通訊協定是否一致,編碼風格是否一致;
功能性:代碼正確得實現了商務邏輯;
可維護性:代碼邏輯是有層次的,是容易修改的;
高效性:代碼實現在時間和空間的使用上是高效的;
就這麼多吧,sql方面還有很多需要學習的地方,發現以前寫的出的sql現在覺得很困難了,各位,有沒有學習提高sql的方法,或推薦的書。以前系統學過sql後幾個月沒用,就一下生疏了,然後重複撿起來,再生疏,痛點複雜點的sql頭緒會很亂,有好的訓練方法嗎?
讓我們繼續前行
----------------------------------------------------------------------
努力不一定成功,但不努力肯定不會成功。
共勉