參考:php
基本數據類型 | 字節 | 範圍 | 默認值 | |
---|---|---|---|---|
byte | 8-bit 1個字節 | -128 ~ 127 | 0 | |
short | 16-bit 2個字節 | -32768 ~ 32767 | 0 | |
int | 32-bit 4個字節 | -2^31 ~ 2^31 - 1 | 0 | |
long | 64-bit 8個字節 | -2^63 ~ 2^63 -1 | 0L | |
float | 32-bit 4個字節 | 0.0f | ||
double | 64-bit 8個字節 | 0.0d | ||
boolean | 1-bit | false | ||
char | 16-bit unicode字符 | '\u0000'~'\uffff' | '\u0000' |
char = '中文'
能夠經過編譯麼?能夠。html
public class primitivetype {
public static void main(String[] args) {
char i = '中';
System.out.println(i);
}
}
複製代碼
能夠運行輸出'中'前端
Java中的一個char採用的是Unicode編碼集,佔用兩個字節,而一箇中文字符也是兩個字節,所以Java中的char是能夠表示一箇中文字符的。java
可是在C/C++中因爲採用的字符編碼集是ASCII,只有一個字節,所以是沒辦法表示一箇中文字符的。node
Java中的char是否能夠存儲一箇中文字符之理解字符字節以及編碼集mysql
java中char類型固定佔2個字節。(注:char類型也能夠存儲一個漢字)。web
以utf8爲例,utf8是一個變長編碼標準,能夠以1~4個字節表示一個字符,而中文佔3個字節,ascII字符佔1個字節。算法
那麼爲何咱們在java裏面能夠用一個char來表示一箇中文呢?spring
由於java是以unicode做爲編碼方式的。unicode是一個定長的編碼標準,每一個字符都是2個字節,也就是1個char類型的空間。sql
在編譯時會把utf8的中文字符轉換成對應的unicode來進行傳輸運算。
String採用一種更靈活的方式進行存儲。在String中,一個英文字符佔1個字節,而中文字符根據編碼的不一樣所佔字節數也不一樣。在UTF-8編碼下,一箇中文字符佔3個字節;而使用GBK編碼時一箇中文字符佔2個字節。測試代碼以下
中文並不必定是佔兩個字節的,具體佔多少字節是跟具體的編碼方式相關的。 好比說:GB23十二、GBK、GB18030 編碼是佔用兩個字節的,可是 UTF-8 編碼的話至少須要佔用三個字節。
MVC模式是軟件工程中的一種軟件架構模式,把軟件系統分爲三個基本部分:模型、視圖和控制器。
mvc是一種建構網站的方法或思想,設計理念。mvc不是框架,而框架是基於mvc思想。
在早期java web,主要使用jsp + java bean模式,jsp與java bean產生嚴重耦合。出現了前端後端相互依賴的問題。
因而出現了servlet + jsp + java bean。 servlet是controller jsp是view 各自java bean 是model 對於後端來講,因爲控制器和模型層的分離使得許多代碼能夠重用。 mvc的經典框架 struts1/struts2和做爲模型層的hibernate紛紛出現。
執行原理
假如輸入maps.google.com
dns:domain name system 保存域名和鏈接的ip地址,每個url都有惟一的ip地址。
爲了找到dns記錄,瀏覽器會依次檢查如下4種緩存
Internet Service Provider,簡稱ISP
爲了讓個人計算機鏈接到託管maps.google.com的服務器,我須要maps.google.com的IP地址。DNS查詢的目的是在internet上搜索多個DNS服務器,直到找到網站的正確IP地址。這種類型的搜索被稱爲遞歸搜索,由於搜索將在DNS服務器和DNS服務器之間重複進行,直到找到咱們須要的IP地址,或者返回一個錯誤響應說沒法找到它爲止。
在這種狀況下,咱們將把ISP的DNS服務器稱爲DNS遞歸器,它的職責是經過詢問internet上的其餘DNS服務器來找到想要的域名的正確IP地址。其餘DNS服務器稱爲名稱服務器,由於它們基於網站域名的域架構執行DNS搜索。
HTTP協議即超文本傳送協議(Hypertext Transfer Protocol ),是Web聯網的基礎,也是手機聯網經常使用的協議之一,HTTP協議是創建在TCP協議之上的一種應用。
一旦瀏覽器接收到正確的IP地址,它將與匹配IP地址以傳輸信息的服務器創建TCP鏈接。三次握手。
爲了在您的計算機(客戶端)和服務器之間傳輸數據包,創建一個TCP鏈接很是重要。這個鏈接是經過一個叫作TCP/IP三方握手的過程創建的。這是一個三個步驟,其中客戶端和服務器交換SYN(同步)和ACK(確認)消息來創建鏈接。
爲了保證服務端能收接受到客戶端的信息並能作出正確的應答而進行前兩次(第一次和第二次)握手,爲了保證客戶端可以接收到服務端的信息並能作出正確的應答而進行後兩次(第二次和第三次)握手。
好比get請求 localhost:8080
Host: localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Cookie: JSESSIONID=8051806AE26B8CAB93BA03AC32A2191E; JSESSIONID=63AB1FE24ECF5F0930743468B802818B
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
複製代碼
該服務器包含一個web服務器(好比apache)。接收來自瀏覽器的請求並將其傳遞給請求處理程序以讀取和生成響應。請求處理程序是一個程序(用php等編寫)用於讀取請求、其頭部和cookies,以檢查所請求的內容,並在須要時更新服務器上的信息。而後它將以特定的格式(JSON、XML、HTML)組裝響應。
服務器響應包含您請求的web頁面、狀態代碼、壓縮類型(內容編碼)、如何緩存頁面(緩存控制)、要設置的任何cookie、隱私信息等。
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Language: zh-CN
Content-Length: 97
Date: Wed, 04 Jul 2018 08:04:54 GMT
複製代碼
狀態碼:
瀏覽器分階段顯示HTML內容。首先,它將呈現裸骨HTML骨架。而後,它將檢查HTML標記併發出GET請求,請求web頁面上的其餘元素,如圖像、CSS樣式表、JavaScript文件等。這些靜態文件被瀏覽器緩存,這樣下次訪問頁面時就沒必要再取回它們了。最後,你會看到網頁出如今你的瀏覽器上。
hashmap是基於哈希表即散列表的。
hashmap經過hashCode方法計算hash值,hash值是經過key對象來計算。hash值用來找到存儲Entry的正確位置。
hashmap使用equals方法來查找在get()時要檢索的鍵的值,並在put()時查找該鍵是否已經存在。
衝突意味着有多個鍵擁有一樣的hash值,在這種狀況下entry對象將會存儲在了同一個linkedlist裏。
HashMap在java中使用內部 Node<K,V>來存儲映射。HashMap基於散列算法,並在鍵上使用hashCode()和equals()方法進行get和put操做。
HashMap使用單個鏈表來存儲元素,這些元素稱爲bucket。當咱們調用put方法時,將使用key的hashCode來肯定存儲映射的bucket。
一旦肯定了bucket,就使用hashCode檢查是否已經有一個具備相同hashCode的鍵。若是存在一個具備相同hashCode的現有鍵,則在key上使用equals()方法。若是equals返回true,那麼value將被覆蓋,不然將對這個單獨連接的list bucket建立一個新的映射。若是沒有具備相同hashCode的鍵,則將映射插入到bucket中。
hashmap 有一個表
**
* The table, resized as necessary. Length MUST Always be a power of two.
*/
transient Node<K,V>[] table;
複製代碼
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
複製代碼
put方法,注意鏈表中是紅黑樹的實現
TreeNode節點,這個類有很是多的方法
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
TreeNode<K,V> parent; // red-black tree links
TreeNode<K,V> left;
TreeNode<K,V> right;
TreeNode<K,V> prev; // needed to unlink next upon deletion
boolean red;
TreeNode(int hash, K key, V val, Node<K,V> next) {
super(hash, key, val, next);
}
}
複製代碼
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
/** * Implements Map.put and related methods * * @param hash hash for key * @param key the key * @param value the value to put * @param onlyIfAbsent if true, don't change existing value * @param evict if false, the table is in creation mode. * @return previous value, or null if none */
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
複製代碼
gc須要完成的3件事情
- 何時回收?
- 哪些內存須要回收?
- 如何回收?
對堆進行回收以前首先要肯定對象之中哪些還「存活」,哪些「死去」。
引用計數算法
可達性分析算法 這個算法的基本思路就是經過一系列的稱爲「GC Roots」的對象做爲起始點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈(Reference Chain),當一個對象到GC Roots沒有任何引用鏈相連(用圖論的話來講,就是從GC Roots到這個對象不可達)時,則證實此對象是不可用的。
在java中,可做爲GC Roots的對象包括如下幾種:
Object obj=new Object()
這類的引用,只要強引用還存在,垃圾收集器永遠不會回收掉被引用的對象。永久代的垃圾回收主要回收兩部分
最基礎的收集算法,"mark-sweep"標記-清除算法。
算法分爲「標記」和「清除」兩個階段:首先標記出全部須要回收的對象,在標記完成後統一回收全部被標記的對象,它的標記過程其實在前一節講述對象標記斷定時已經介紹過了。之因此說它是最基礎的收集算法,是由於後續的收集算法都是基於這種思路並對其不足進行改進而獲得的。
它的主要不足有兩個:一個是效率問題,標記和清除兩個過程的效率都不高;另外一個是空間問題,標記清除以後會產生大量不連續的內存碎片,空間碎片太多可能會致使之後在程序運行過程當中須要分配較大對象時,沒法找到足夠的連續內存而不得不提早觸發另外一次垃圾收集動做。
爲了解決效率問題,一種稱爲「複製」(Copying)的收集算法出現了,它將可用內存按容量劃分爲大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活着的對象複製到另一塊上面,而後再把已使用過的內存空間一次清理掉。這樣使得每次都是對整個半區進行內存回收,內存分配時也就不用考慮內存碎片等複雜狀況,只要移動堆頂指針,按順序分配內存便可,實現簡單,運行高效。只是這種算法的代價是將內存縮小爲了原來的一半,未免過高了一點。
新生代中的對象98%是「朝生夕死」的,因此並不須要按照1:1的比例來劃份內存空間,而是將內存分爲一塊較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中一塊Survivor。當回收時,將Eden和Survivor中還存活着的對象一次性地複製到另一塊Survivor空間上,最後清理掉Eden和剛纔用過的Survivor空間。HotSpot虛擬機默認Eden和Survivor的大小比例是8:1,也就是每次新生代中可用內存空間爲整個新生代容量的90%(80%+10%),只有10%的內存會被「浪費」。固然,98%的對象可回收只是通常場景下的數據,咱們沒有辦法保證每次回收都只有很少於10%的對象存活,當Survivor空間不夠用時,須要依賴其餘內存(這裏指老年代)進行分配擔保(Handle Promotion)。
內存的分配擔保就比如咱們去銀行借款,若是咱們信譽很好,在98%的狀況下都能按時償還,因而銀行可能會默認咱們下一次也能按時按量地償還貸款,只須要有一個擔保人能保證若是我不能還款時,能夠從他的帳戶扣錢,那銀行就認爲沒有風險了。內存的分配擔保也同樣,若是另一塊Survivor空間沒有足夠空間存放上一次新生代收集下來的存活對象時,這些對象將直接經過分配擔保機制進入老年代。標記過程仍然與「標記-清除」算法同樣,但後續步驟不是直接對可回收對象進行清理,而是讓全部存活的對象都向一端移動,而後直接清理掉端邊界之外的內存。
只是根據對象存活週期的不一樣將內存劃分爲幾塊。通常是把Java堆分爲新生代和老年代,這樣就能夠根據各個年代的特色採用最適當的收集算法。
在新生代中,每次垃圾收集時都發現有大批對象死去,只有少許存活,那就選用複製算法,只須要付出少許存活對象的複製成本就能夠完成收集。
而老年代中由於對象存活率高、沒有額外空間對它進行分配擔保,就必須使用「標記—清理」或者「標記—整理」算法來進行回收。
若是說收集算法是內存回收的方法論,那麼垃圾收集器就是內存回收的具體實現
eden滿了minor gc,升到老年代的對象大於老年代剩餘空間full gc,或者小於時被HandlePromotionFailure參數強制full gc;gc與非gc時間耗時超過了GCTimeRatio的限制引起OOM,調優諸如經過NewRatio控制新生代老年代比例,經過MaxTenuringThreshold控制進入老年前生存次數等
參考:icyfenix.iteye.com/blog/715301
慢sql特色 1 數據庫CPU負載高。通常是查詢語句中有不少計算邏輯,致使數據庫cpu負載。 2 IO負載高致使服務器卡住。這個通常和全表查詢沒索引有關係。 3 查詢語句正常,索引正常可是仍是慢。若是表面上索引正常,可是查詢慢,須要看看是否索引沒有生效。
打開MySQL的慢查詢日誌來進一步定位問題。mysql提供了慢查詢日誌,日誌會記錄全部執行時間超過long_query_time的sql
要開啓日誌,須要在MySQL的配置文件的mysqlld項下配置慢查詢日誌開啓。
有些SQL雖然出如今慢查詢日誌中,但未必是其自己的性能問題,多是由於鎖等待,服務器壓力高等等。
須要分析SQL語句真實的執行計劃,而不是看從新執行一遍SQL時,花費了多少時間,由自帶的慢查詢日誌或者開源的慢查詢系統定位到具體的出問題的SQL,而後使用Explain工具來逐步調優,瞭解 MySQL 在執行這條數據時的一些細節,好比是否進行了優化、是否使用了索引等等。基於 Explain 的返回結果咱們就能夠根據 MySQL 的執行細節進一步分析是否應該優化搜索、怎樣優化索引。
兩個表,customers,orders
customers
cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | |
---|---|---|---|---|---|---|---|---|---|
10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | |
10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | |
10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | |
10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | |
10005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL |
內部聯結
orders
order_num | order_date | cust_id |
---|---|---|
20005 | 2005-09-01 00:00:00 | 10001 |
20006 | 2005-09-12 00:00:00 | 10003 |
20007 | 2005-09-30 00:00:00 | 10004 |
20008 | 2005-10-03 00:00:00 | 10005 |
20009 | 2005-10-08 00:00:00 | 10001 |
SELECT customers.cust_id,orders.order_num FROM customers INNER JOIN orders ON customers.cust_id = orders.cust_id;
複製代碼
cust_id | order_num |
---|---|
10001 | 20005 |
10001 | 20009 |
10003 | 20006 |
10004 | 20007 |
10005 | 20008 |
外部聯結
SELECT customers.cust_id,orders.order_num FROM customers LEFT OUTER JOIN orders ON customers.cust_id = orders.cust_id
複製代碼
cust_id | order_num |
---|---|
10001 | 20005 |
10001 | 20009 |
10002 | NULL |
10003 | 20006 |
10004 | 20007 |
10005 | 20008 |
SELECT customers.cust_id,orders.order_num FROM customers RIGHT OUTER JOIN orders ON customers.cust_id = orders.cust_id
複製代碼
cust_id | order_num |
---|---|
10001 | 20005 |
10001 | 20009 |
10003 | 20006 |
10004 | 20007 |
10005 | 20008 |
在使用OUTER JOIN
語法時,必須使用RIGHT
或LEFT
關鍵字 指定包括其全部行的表(RIGHT
指出的是OUTER JOIN
右邊的表,而LEFT
指出的是OUTER JOIN
左邊的表)。上面的例子使用LEFT OUTER JOIN
從FROM
子句的左邊表(customers表)中選擇全部行。爲了從右邊的表中選擇全部行,應該使用RIGHT OUTER JOIN
.
當表的數據量比較大時,查詢操做會比較耗時。創建索引是加快查詢速度的有效手段。數據庫索引相似於圖書後面的索引,能快速定位到須要查詢的內容。
數據庫索引有多種類型,常見索引包括順序文件上的索引
,b+樹索引
、哈希索引
、位圖索引
、全文索引
。
在mysql中,存儲引擎先在索引中找到對應值,而後根據匹配的索引記錄找到對應的數據行。
mysql先在索引上按值進行查找,而後返回全部包含該值的數據行。
索引能夠包含一個或多個列的值。若是索引包含多個列,那麼列的順序也十分重要,由於mysql只能高效地使用索引的最左前綴列。
索引可讓服務器快速定位到表的指定位置 索引的優勢:
mysql支持的數據類型很是多,選擇正確的數據類型對於得到高性能相當重要。無論存儲哪一種類型的數據,下面幾個簡單的原則都有助於做出更好選擇。
索引的代價:1.須要佔硬盤空間 2.一旦插入新的數據,須要從新建索引 高性能索引策略
優化數據訪問
重構查詢的方式
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if(root == null){
return res;
}
Queue<TreeNode> qp = new LinkedList<>();
qp.offer(root);
while(!qp.isEmpty()){
List<Integer> level = new ArrayList<>();
TreeNode node = null;
int lenL = qp.size();
for(int i = 0; i < lenL; i++){
node = qp.poll();
level.add(node.val);
if(node.left != null){
qp.offer(node.left);
}
if(node.right != null){
qp.offer(node.right);
}
}
res.add(level);
}
return res;
}
}
複製代碼