我們到底能走多遠系列(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,queue
來自《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("queue 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("queue 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頭緒會很亂,有好的訓練方法嗎?
讓我們繼續前行
----------------------------------------------------------------------
努力不一定成功,但不努力肯定不會成功。
共勉