JAVA 與 MyCat(4) XML解析詳解
通過mycat來學習java了^^。
前一篇講到了load方法:
private void load(String dtdFile, String xmlFile) { InputStream dtd = null; InputStream xml = null; try { dtd = XMLSchemaLoader.class.getResourceAsStream(dtdFile); xml = XMLSchemaLoader.class.getResourceAsStream(xmlFile); Element root = ConfigUtil.getDocument(dtd, xml).getDocumentElement(); // 先載入所有的DataHost loadDataHosts(root); // 再載入所有的DataNode loadDataNodes(root); // 最後載入所有的Schema loadSchemas(root); } catch (ConfigException e) { throw e; } catch (Exception e) { throw new ConfigException(e); } finally { if (dtd != null) { try { dtd.close(); } catch (IOException e) { } } if (xml != null) { try { xml.close(); } catch (IOException e) { } } } }
第一個知識點:getResourceAsStream(fileName)的檔案位置,已經講了,接著往下看:
Element root = ConfigUtil.getDocument(dtd, xml).getDocumentElement();
看看ConfigUtil.getDocument(dtd, xml)方法的內容,此時方法的引數值為/rule.dtd和/rule.xml:
該方法就是通過對rule.xml的解析,返回一個w3c的Document型別,用來存放xml檔案內容。這又是一個知識點:public static Document getDocument(final InputStream dtd, InputStream xml) throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); factory.setNamespaceAware(false); DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(new EntityResolver() { @Override public InputSource resolveEntity(String publicId, String systemId) { return new InputSource(dtd); } }); builder.setErrorHandler(new ErrorHandler() { @Override public void warning(SAXParseException e) { } @Override public void error(SAXParseException e) throws SAXException { throw e; } @Override public void fatalError(SAXParseException e) throws SAXException { throw e; } }); return builder.parse(xml); }
XML文件解析:四種方式的簡單總結
對XML的解析網上有許多文章,有興趣可以搜一下,一大把,這裡不做過多重複,只對重點列舉一下:
以如下XML文件進行展示:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mycat:rule SYSTEM "rule.dtd"> <mycat:rule xmlns:mycat="http://io.mycat/"> <tableRule name="mod-long"> <rule> <columns>user_id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule> <tableRule name="mod-long-from"> <rule> <columns>from_user_id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule> <tableRule name="mod-long-to"> <rule> <columns>to_user_id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule> <function name="mod-long" class="io.mycat.route.function.PartitionByMod"> <!-- how many data nodes --> <property name="count">2</property> <property name="defaultNode">0</property> </function> </mycat:rule>
1.DOM解析,適合XML檔案小的場景
最原始的解析方式,將整個XML文件讀入記憶體,按層次解析成一棵樹,容易理解,可以隨機訪問樹的任意部分,但如果XML文件比較大,會佔用大量記憶體。這種解析方式適用於XML檔案比較小的場景。
package io.mycat.test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
public class DOMrw {
public static void main(String[] args) {
parse();
}
public static void parse() {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = dbf.newDocumentBuilder();
InputStream in = DOMrw.class.getResourceAsStream("/rule.xml");
Document doc = builder.parse(in);
// root <mycat:rule>
Element root = doc.getDocumentElement();
System.out.print(root.getNodeName());
NamedNodeMap nnm = root.getAttributes();
for (int i = 0; i < nnm.getLength(); i++) {
Node n = nnm.item(i);
System.out.print(" " + n.getNodeName() + "=" + n.getNodeValue() + " ");
}
System.out.println();
// all tableRule, function node
NodeList nodes = root.getChildNodes();
print(nodes, 1);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void print(NodeList nodes, int ind) {
NamedNodeMap nnm;
String txt;
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.TEXT_NODE) {
txt = node.getTextContent();
if (txt.replaceAll("\n", "").replaceAll("\t", "").replaceAll(" ", "").length() > 0) {
for (int j = 0; j < ind; j++) {
System.out.print(" ");
}
System.out.print("[" + node.getTextContent() + "]");
System.out.println();
}
}
if (node.getNodeType() == Node.ELEMENT_NODE) {
for (int j = 0; j < ind; j++) {
System.out.print(" ");
}
System.out.print(node.getNodeName());
nnm = node.getAttributes();
for (int j = 0; j < nnm.getLength(); j++) {
Node n = nnm.item(j);
System.out.print(" " + n.getNodeName() + "=" + n.getNodeValue() + " ");
}
System.out.println();
NodeList nds = node.getChildNodes();
if (nds.getLength() == 0) {
System.out.print(node.getTextContent());
} else {
print(nds, ind + 1);
}
}
}
}
}
執行結果:
mycat:rule xmlns:mycat=http://io.mycat/
tableRule name=mod-long
rule
columns
[user_id]
algorithm
[mod-long]
tableRule name=mod-long-from
rule
columns
[from_user_id]
algorithm
[mod-long]
function class=io.mycat.route.function.PartitionByMod name=mod-long
property name=count
[2]
property name=defaultNode
[0]
上面的java程式碼是xml的解析,也就是讀,把xml檔案裡的內容全部打印出來。上面程式碼裡,沒有寫。
2.SAX解析,記憶體佔用少,響應快,適合XML大文件
SAX與DOM正好相反,佔用記憶體少,但只能順序訪問,不能隨機訪問。SAX在解析XML文件時,按順序會遇到各種文件元素,遇到時就觸發相應的事件,例如startDocument()文件開始事件,endDocument()文件結束事件,startElement()元素開始事件等等,我們重寫這些事件方法,就可以完成我們解析的目的,所以SAX也稱為事件驅動解析。
SAX不會將整個XML文件都事先讀入記憶體,讀過的部分也不保證快取在記憶體裡,所以適合XML大文件的讀取,但只能順序讀取。由於是邊讀邊觸發事件邊處理,所以SAX的響應速度很快。
XML文件裡的元素種類很多,所以對應的事件也很多,但最常用的是startDocument()、endDocument()、startElement()、endElement()、characters()幾個。
package io.mycat.test;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SAXr {
public static void main(String[] args) {
parse();
// write();
}
public static void parse() {
SAXParserFactory saxf = SAXParserFactory.newInstance();
try {
SAXParser saxparser = saxf.newSAXParser();
InputStream in = DOMrw.class.getResourceAsStream("/rule.xml");
saxparser.parse(in, new MySAXHandler());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MySAXHandler extends DefaultHandler {
boolean hasAttribute = false;
Attributes attributes = null;
public void startDocument() throws SAXException {
System.out.println("文件開始");
}
public void endDocument() throws SAXException {
System.out.println("文件結束");
}
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (!uri.isEmpty()) {
System.out.print("uri=" + uri + " ");
}
if (!localName.isEmpty()) {
System.out.print("localName=" + localName + " ");
}
if (!qName.isEmpty()) {
System.out.print("qName=" + qName + " ");
}
for (int i = 0; i < attributes.getLength(); i++) {
System.out.print(attributes.getQName(i) + ":" + attributes.getValue(i) + " ");
}
// System.out.println();
}
public void endElement(String uri, String localName, String qName) throws SAXException {
}
// characters該當就相當於DOM裡的TEXT_NODE一樣,處理文字資訊
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.print(new String(ch, start, length));
}
}
執行結果:
文件開始
qName=mycat:rule xmlns:mycat:http://io.mycat/
qName=tableRule name:mod-long
qName=rule
qName=columns user_id
qName=algorithm mod-long
qName=tableRule name:mod-long-from
qName=rule
qName=columns from_user_id
qName=algorithm mod-long
qName=tableRule name:mod-long-to
qName=rule
qName=columns to_user_id
qName=algorithm mod-long
qName=function name:mod-long class:io.mycat.route.function.PartitionByMod
qName=property name:count 2
qName=property name:defaultNode 0
文件結束
SAX在解析時,需要指定handler類,該類繼承DefaultHandler,實現各種事件的處理。
3.JDOM解析,使用簡單
前面的DOM方式和SAX方式解析XML程式碼編寫比較複雜,為了簡化程式碼可以使用JDOM,而且完成相同的功能JDOM的程式碼更高效,但是JDOM不能解決所有的問題。JDOM的目的就是為了解決80%最常見的問題,使這些問題的解決得到極大簡化,而另外20%不常見問題,則需要自己編碼解決,這些問題很少遇到,可以忽略。所以JDOM還是很值得考慮使用的。
JDOM沒有自己的解析器,所以使用的是SAX解析器,但在使用上更類似於DOM,更容易理解。
package io.mycat.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
public class JDOMr {
public static void main(String[] args) {
parse();
// write();
}
public static void parse() {
SAXBuilder saxBuilder = new SAXBuilder();
try {
InputStream in = JDOMr.class.getResourceAsStream("/rule.xml");
Document document = saxBuilder.build(in); // 這裡的Document是jdom2的Document
Element root = document.getRootElement(); // 這裡的Element是jdom2的Element
System.out.print("name=" + root.getName() + " ");
System.out.print("NamespacePrefix=" + root.getNamespacePrefix() + " ");
System.out.print("NamespaceURI=" + root.getNamespaceURI() + " ");
List<Attribute> lattr = root.getAttributes();
for (Attribute attr : lattr) {
System.out.print(" " + attr.getName() + "=" + attr.getValue() + " ");
}
System.out.println();
// all tableRule, function node
List<Element> children = root.getChildren();
print(children, 1);
} catch (JDOMException | IOException e) {
e.printStackTrace();
}
}
private static void print(List<Element> children, int ind) {
for (Element elt : children) {
for (int j = 0; j < ind; j++) {
System.out.print(" ");
}
System.out.print(elt.getName());
List<Attribute> lattr = elt.getAttributes();
for (Attribute attr : lattr) {
System.out.print(" " + attr.getName() + "=" + attr.getValue() + " ");
}
String txt = elt.getTextTrim();
if (txt.length() > 0) {
System.out.print("[" + txt + "]");
}
System.out.println();
// all tableRule, function node
List<Element> ch = elt.getChildren();
print(ch, ind + 1);
}
}
}
執行結果:
name=rule NamespacePrefix=mycat NamespaceURI=http://io.mycat/
tableRule name=mod-long
rule
columns[user_id]
algorithm[mod-long]
tableRule name=mod-long-from
rule
columns[from_user_id]
algorithm[mod-long]
tableRule name=mod-long-to
rule
columns[to_user_id]
algorithm[mod-long]
function name=mod-long class=io.mycat.route.function.PartitionByMod
property name=count [2]
property name=defaultNode [0]
通過上面程式碼,可以很明顯地看到,輸出同樣的結束,JDOM的程式碼要少的多。
4.DOM4J解析、最好的解析方式
DOM4J是JDOM的改進,一開始DOM4J只是JDOM的一個智慧分支,後來發展成一款獨立的開源軟體,DOM4J不但可以解決所有的XML解析問題,還包括整合的 XPath 支援、XML Schema 支援以及用於大文件或流化文件的基於事件的處理。總之,DOM4J效能優異、功能強大、極端易用使用。
越來越多的軟體在使用DOM4J,連 Sun 的 JAXM 也在用 DOM4J。所以使用DOM4J處理XML是不錯的選擇。
package io.mycat.test.xml;
import java.io.InputStream;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class DOM4Jr {
public static void main(String[] args) {
parse();
// write();
}
public static void parse() {
SAXReader reader = new SAXReader();
try {
InputStream in = JDOMr.class.getResourceAsStream("/rule.xml");
Document document = reader.read(in); // 這裡的Document是dom4j的Document
Element root = document.getRootElement(); // 這裡的Element是dom4j的Element
System.out.print("name=" + root.getName() + " ");
System.out.print("NamespacePrefix=" + root.getNamespacePrefix() + " ");
System.out.print("NamespaceURI=" + root.getNamespaceURI() + " ");
List<Attribute> lattr = root.attributes();
for (Attribute attr : lattr) {
System.out.print(" " + attr.getName() + "=" + attr.getValue() + " ");
}
System.out.println();
// all tableRule, function node
List<Element> children = root.elements();
print(children, 1);
} catch (DocumentException e) {
e.printStackTrace();
}
}
private static void print(List<Element> children, int ind) {
for (Element elt : children) {
for (int j = 0; j < ind; j++) {
System.out.print(" ");
}
System.out.print(elt.getName());
List<Attribute> lattr = elt.attributes();
for (Attribute attr : lattr) {
System.out.print(" " + attr.getName() + "=" + attr.getValue() + " ");
}
String txt = elt.getTextTrim();
if (txt.length() > 0) {
System.out.print("[" + txt + "]");
}
System.out.println();
// all tableRule, function node
List<Element> ch = elt.elements();
print(ch, ind + 1);
}
}
}
執行結果:
name=rule NamespacePrefix=mycat NamespaceURI=http://io.mycat/
tableRule name=mod-long
rule
columns[user_id]
algorithm[mod-long]
tableRule name=mod-long-from
rule
columns[from_user_id]
algorithm[mod-long]
tableRule name=mod-long-to
rule
columns[to_user_id]
algorithm[mod-long]
function name=mod-long class=io.mycat.route.function.PartitionByMod
property name=count [2]
property name=defaultNode [0]
從上面程式碼可以看出,DOM4J與JDOM的程式碼非常類似,程式碼依然簡練,但DOM4J提供的方法更多,完成的功能更多,效率也更高。
上面就是JAVA的XML的四種解析方式,總的來說,優先使用DOM4J的方式。
現在回過頭來再看一下MyCat的XML解析:
public static Document getDocument(final InputStream dtd, InputStream xml) throws ParserConfigurationException,
SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver(new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(dtd);
}
});
builder.setErrorHandler(new ErrorHandler() {
@Override
public void warning(SAXParseException e) {
}
@Override
public void error(SAXParseException e) throws SAXException {
throw e;
}
@Override
public void fatalError(SAXParseException e) throws SAXException {
throw e;
}
});
return builder.parse(xml);
}
首先:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
這一段用的是javax.xml.parsers包裡的JAVA自帶的基本類。接下來:
builder.setEntityResolver(new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(dtd);
}
});
builder.setErrorHandler(new ErrorHandler() {
@Override
public void warning(SAXParseException e) {
}
@Override
public void error(SAXParseException e) throws SAXException {
throw e;
}
@Override
public void fatalError(SAXParseException e) throws SAXException {
throw e;
}
});
這一段用的又是SAX的XML解析,最後:
return builder.parse(xml);
返回的又是org.w3c.dom包的Document類。總的感覺,又點不倫不類,當然不是說這樣不能用,就是覺得風格不統一。其實,看SAX部分的作用,就是為了用DTD檔案進行XML的校驗,而這種校驗用JDOM或DOM4J也可以完成。所以可以改成JDOM或DOM4J的統一風格,本人將這段程式碼改成DOM4J的方式:
public static Document getDocument(final InputStream dtd, InputStream xml) throws DocumentException {
SAXReader reader = new SAXReader();
reader.setValidation(true);
reader.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(dtd);
}
});
return reader.read(xml);
}
這以看到,程式碼相當簡潔,而完成的功能又完全一樣。這裡的Document是DOM4J裡的Document類,不再引用W3C的Document類,風格相當統一。本人已將MyCat裡XML解析全部修改成DOM4J的方式,程式碼簡潔不少。上面內容,如有問題,歡迎指正。
相關推薦
JAVA 與 MyCat(4) XML解析詳解
通過mycat來學習java了^^。 前一篇講到了load方法: private void load(String dtdFile, String xmlFile) { InputStream dtd = null; InputStream xml =
JAVA 與 MyCat(2) 單例模式
通過mycat來學習java了^^。 接前一篇:http://blog.csdn.net/john_chang11/article/details/78668667 MycatServer server = MycatServer.getInstance(); 獲取My
JAVA 與 MyCat(5) 類的載入 Java內省/反射機制 註解Annotation 詳解
通過mycat來學習java了^^。 上一篇瞭解了XML解析的四種方式,並對MyCat的原始碼進行了修改,這一篇接著往下看: dtd = XMLRuleLoader.class.getResourceAsStream(dtdFile); x
JAVA 與 MyCat(3) 關於getResourceAsStream(fileName)的檔案位置
通過mycat來學習java了^^。 前一篇文章介紹了單例模式建立了MycatServer單例項,下面一起看看MycatServer初始化方法的內容: private MycatServer() { // 讀取檔案配置 this.config = ne
FastDFS的配置、部署與API使用解讀(4)FastDFS配置詳解之Client配置
一種方式是通過呼叫ClientGlobal類的初始化方法對配置檔案進行載入,另一種是通過呼叫API逐一設定配置引數。後一種方式對於使用Zookeeper等載入屬性的方式很方便。 1. 載入配置檔案: String configFileName = "conf/dfs-c
java基礎回顧(五)線程詳解以及synchronized關鍵字
dom com stack 相互 ++ 關於 而是 。。 str 本文將從線程的使用方式、源碼、synchronized關鍵字的使用方式和陷阱以及一些例子展開java線程和synchronized關鍵字的內容。 一、線程的概念 線程就是程序中單獨順序的流控制。線程本 身不能
目標檢測與分割(三):SSD詳解
SSD github : https://github.com/weiliu89/caffe/tree/ssd SSD paper : https://arxiv.org/abs/1512.02325 SSD eccv2016 slide pdf : http://d
Java設計模式(五) 原型模式詳解
一、引言 在開發過程中,有時會遇到為一個類建立多個例項的情況,這些例項內部成員往往完全相同或有細微的差異,而且例項的建立開銷比較大或者需要輸入較多引數,如果能通過複製一個已建立的物件例
Java學習總結(21)——XML文檔解析:DOM解析,SAX解析
Oz 學習總結 AR javax exce 天氣 efault ray XP 一.XML簡介1.可擴展性標記語言(eXtensible Markup Language)2.XML用於描述數據3.應用場合:(1)持久化存儲數據(2)數據交換(3)數據配置4.XML語法(1)文
Java並發(4)- synchronized與CAS
線程 static ima bubuko nts 就是 incr 獲取 阻塞 引言 上一篇文章中我們說過,volatile通過lock指令保證了可見性、有序性以及“部分”原子性。但在大部分並發問題中,都需要保證操作的原子性,volatile並不具有該功能,這時就需要通過其他
Java併發程式設計(4):守護執行緒與執行緒阻塞的四種情況
守護執行緒Java中有兩類執行緒:User Thread(使用者執行緒)、Daemon Thread(守護執行緒) 使用者執行緒即執行在前臺的執行緒,而守護執行緒是執行在後臺的執行緒。 守護執行緒作用是為其他前臺執行緒的執行提供便利服務,而且僅在普通、非守護執行緒仍然執行時才需要,比如垃圾回收執行緒就是一個
java基礎筆記(4)----數組
adding 類型 說明 spa 初始化 pac align int nbsp 介紹: 數組是一種數據類型,是引用類型,是一塊連續的內存空間,用於存儲和管理相同類型的多個數據。 定義:-- > 數組的聲明方式 先聲明,在開辟內存空間--> int [] a;
卷積神經網絡學習筆記與心得(4)池化
設計者 位置 浪費 需要 三種 限制 右移 理論 alt 圖片經過卷積、激活後的結果一般帶有大量原圖信息。 上圖中卷積核提取的是豎直方向上的連續像素,但是,被增強的像素只占了結果的1/3,對於多層網絡,其余重要性較低的信息也被傳入了下一層網絡,造成了不必要的浪費,因此需要
java虛擬機(4)--類加載機制
sta 代理技術 賦值 工作 開始 外部 equals() ioe con 類加載機制 類是在運行期間第一次使用時動態加載的,而不是編譯時期一次性加載。因為如果在編譯時期一次性加載,那麽會占用很多的內存。 1.1 類的生命周期 包括以下 7 個階段: 加
Java並發(4)
環境 訪問 obj 元素 dac app ole 可能 最新 java中的線程安全是什麽: 就是線程同步的意思,就是當一個程序對一個線程安全的方法或者語句進行訪問的時候,其他的不能再對他進行操作了,必須等到這次訪問結束以後才能對這個線程安全的方法進行訪問 什麽叫線程安全:
「深入Java虛擬機(4)」:類加載機制
來講 合並 field 數字 對象 例如 二進制 種類 jar 類加載過程 類從被加載到虛擬機內存中開始,到卸載出內存為止,它的整個生命周期包括:加載、驗證、準備、解析、初始化、使用和卸載七個階段。 其中類加載的過程包括了加載、驗證、準備、解析、初始化五個階段。在這五個階段
繼承與派生(4):二義性(三角繼承和菱形繼承)
一般說來,在派生類中對基類成員的訪問應該是唯一的,但是,由於多繼承情況下,可能造成對基類中某成員的訪問出現了不唯一的情況,則稱為對基類成員訪問的二義性問題。 實際上,在上例已經出現過這一問題,回憶一下上例中(參照繼承
使用XWAF框架(5)——XML解析器:CXDP
XWAF推出了自己的組合式XML文件解析器,英文名叫:“CXDP”,是“Combined XML Document Parser”的縮寫。核心程式碼屬XWAF原創,註釋、日誌和幫助文件採用全中文描述,特別適合於中文背景的初級程式設計師學
資料結構——排序與查詢(4)——常見的內部排序演算法大全
這篇博文就讓我水一次,這兩天量產部落格,偷個懶,不過下面的文章都是我自己寫的: 插入排序演算法及其分析 簡單的氣泡排序及其分析 希爾排序及其分析 快速排序演算法及其分析 合併排序演算法及其分析 堆排序演算法及其分析 選擇排序演算法及其分析
Java原始碼系列(4):String,StringBuilder,StringBuffer區別
hi,國慶節後第一篇。首先,祝大家國慶節快樂,然後祝大家上班快樂。 既然上班了,那就知識學起來,今天咱說一下String,StringBuffer和StringBuilder的區別,這是面試必問,但是如果是工作了的小哥哥和小姐姐,就不會傻白甜的問這個問題,但咱還是要知道的,畢竟要