1、Stringjava
public final class String extends Object implements Serializable, Comparable, CharSequence數組
String 類包括的方法可用於檢查序列的單個字符、比較字符串、搜索字符串、提取子字符串、建立字符串副本並將全部字符所有轉換爲大寫或小寫。大小寫映射基於 Character 類指定的 Unicode 標準版。安全
例1:app
import java.util.Arrays;dom
public class TestString {工具
public static void main(String[] args) {性能
byte[] bs = {65,66,67,68,69};測試
//經過字節數組建立字符串對象ui
String str = new String(bs);.net
//將字符穿對象轉換爲字節數組
System.out.println(Arrays.toString(str.getBytes()));//{65,66,67,68,69}
System.out.println(str);//ABCDE
//獲得字節數組指定區間的字符串對象
System.out.println(new String(bs,1,3));//BCD
//建立一個字符串對象,根據指定的值
str = new String("0123456789");
//0序的
System.out.println(str.charAt(3));//3
//字符串鏈接 原字符串不變
System.out.println(str.concat("asd"));//0123456789asd
//是否包含某個子字符串
System.out.println(str.contains("0234"));//false
//某個字符串是否以什麼結尾
System.out.println(str.endsWith(""));//true
//字符串格式化,
System.out.println(String.format("%s攻擊了%s,%s掉了%d滴血", "阿基里斯","赫克託","赫克託",100));//100是自動裝箱
//從前日後找
System.out.println(str.indexOf(52));//4
System.out.println(str.indexOf("345"));//3
System.out.println(str.indexOf("345", 6));//-1
//求長度
System.out.println(str.length());//10
//生成一個新的字符串
System.out.println(str.replace("2", "__"));
//切割字符串
str = "123_5435_1232_545_343_DSF";
System.out.println(Arrays.toString(str.split("_")));
System.out.println(str.substring(8));//_1232_545_343_DSF
System.out.println(str.substring(1, 2));//2
//去掉先後的空白字符
str = " uiu ou ou ou ";
System.out.println(str.trim());
System.out.println();
System.out.println(str);
}
}
例2:
//* 1:在工具類中定義工具方法,對指定的字符串,求出該字符串中,出現指定字符的個數。
//* 2:自定義方法,實現產生一個隨機字符串,長度爲20,每個字符要求所有隨機產生,而後統計該字符串中的大寫字符和小寫字符的個數並以數組形式返回統計的個數
//* 3:自定義方法,針對指定的字符串,返回該字符串的逆序形式。
import java.util.Arrays;
import com.bjsxt.util.MyUtil;
public class TestString1 {
public static void main(String[] args) {
System.out.println(getCharCount("3278239782981", '8'));
String str = getRandomStr(20);
System.out.println(str);
System.out.println(Arrays.toString(getLowerAndUpperCharCount(str)));
}
// 在工具類中定義工具方法,對指定的字符串,求出該字符串中,出現指定字符的個數。
public static int getCharCount(String str , char key){
if(str == null)
return -1;
if(str.isEmpty())
return 0;
int counter = 0;
int len = str.length();
for (int i = 0; i < len; i++) {
//取出每一個字符進行比對
char c = str.charAt(i);
if(key == c)
counter ++;
}
return counter;
}
//自定義方法,實現產生一個隨機字符串,長度爲20,每個字符要求所有隨機產生,而後統計該字符串中的大寫字符和小寫字符的個數並以數組形式返回統計的個數
//隨機產生一個指定長度的字符串
public static String getRandomStr(int length){
String str = "";
for(int i=0;i
//獲得隨機區間的值
int ranNumber = MyUtil.getRandomNumber('A', 'Z'+1);
//隨機大小寫的字符
char ranChar = (char)(Math.random() > 0.5 ? ranNumber : ranNumber + 32);
str = str.concat(Character.toString(ranChar));
}
return str;
}
//針對指定的字符串,統計字符串中大小寫的個數,以數組形式返回。
public static int[] getLowerAndUpperCharCount(String str){
if(str == null)
return null;
if(str.isEmpty())
return null;
int[] count = new int[2];
//統計
int len = str.length();
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
if(Character.isUpperCase(c)){
count[0]++;
}else if(Character.isLowerCase(c)){
count[1]++;
}
}
return count;
}
// 自定義方法,針對指定的字符串,返回該字符串的逆序形式。
public static String reverse(String str){
//逆序取出來,鏈接
if(str == null)
return null;
if(str.isEmpty())
return "";
String newStr = "";
int len = str.length();
for (int i = len-1; i >= 0; i--) {
char c = str.charAt(i);
newStr += c;
}
return newStr;
}
}
2、原碼分析
1:字符串類型底層使用 char[] 實現。是一個final 修飾的數組。
String 類沒有提供對外的任何修改原有字符串的方法。
結論:字符串對象一旦建立,就不能更改。全部的看似對字符串的修改,都不是在原有的字符串對象上的修改,而是會生成一個新的字符串對象。
這樣的特色致使了,在程序中使用字符串對象,會在內存中生成大量的字符串對象的碎片。形成對內存的浪費。
java 對String 進行了特殊的處理,來儘可能的避免這樣的問題。
3、String扣留intern 機制
java 對字符串提供了一種 字符串扣留 intern 機制。
java 對字符串常量 提供了一個 字符串常量池的內存空間。在方法區中。扣留機制的基礎。
字符串常量池由String 類本身維護。
在編譯期一個類有哪些字符串常量就肯定了。在類加載的時候,就會把當前類的全部的字符串常量加載到字符串常量池中。
1:String str = "abc";
在java 語句中,若是存在了一個字符串常量,那麼 String 類的扣留機制 會 自動的判斷 該常量是否存在於 常量池中
若是存在,那麼直接將常量池中的字符串對象的引用返回,不會建立新的字符串對象。
若是在常量池中不存在該常量,那麼就將該常量添加到常量池中,並返回常量池字符串的地址。
這樣的賦值方式會產生[0-1]個字符串對象。
2:String str = new String("123");
首先對字符串常量"123",進行扣留機制的判斷。可能產生[0-1]個對象。
new 出來的String 對象在堆區中被建立。 新的String 對象中的成員 value 指向 常量池中的字符串地址。
這樣的建立對象的方式會產生[1-2]個對象。
要求:使用第一種建立字符串對象的方式。
public class TestInternString {
public static void main(String[] args) {
//產生了一個字符串對象 a ,在常量池中
String a = "a";
//產生了一個字符串對象 b ,在常量池中
String b = "b";
//產生了一個字符串對象 ab ,在常量池中
String s1 = "ab";
//編譯以後 和 a和b 合併,沒有產生 字符串對象,直接指向方法區 "ab";
String s2 = "a"+"b";
//會產生一個新的對象,指向堆的。 涉及到字符串變量的+鏈接的實現。
String s3 = a + b;
//在堆中產生一個新的對象
String s4 = new String("ab");
//若是"ab" 字符串 已經存在於 常量池中,那麼直接返回 常量池的地址。
//若是「ab」 不存在於常量池中。那麼就將"ab" 在運行期動態的添加到常量池,並返回常量池字符串的地址。
//intern 將當前字符串對象動態的添加到常量池中,並返回在常量池中的地址。
String s5 = new String(a+b).intern();
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s1 == s5);//true
}
}
4、StringBuffer和StringBuilder
StringBuffer:
能夠修改的字符串對象。能夠認爲是一個加強版的String。
在原有的String的功能上面(有些功能沒有),增長了對字符串序列的增刪改。
底層使用char[] 數組實現。
StringBuilder是在某些狀況下的替代StringBuffer 類的一個類。和StringBuffer類的用法徹底同樣。API 兼容。
StringBuffer 是線程安全的。
效率相對較低。
StringBuilder 是線程非安全的。
效率更高。
總結:在線程安全的狀況下使用StringBuilder。
例:
/**
* 對於指定的一個字符串,將該字符串的統計表示形式[asdasdasd---a(3)s(3)d(3)]保存到一個StringBuffer中,並最後打印輸出。
* 思路:逐個遍歷字符串中的每一個字符,將統計的結果放到一個StringBuffer中,若是被遍歷的字符尚未出如今
* StringBuffer 中,則在StringBuffer中尾部添加該字符並在該字符後增長 (1) ,若是已經存在 與StringBuffer
* 則將該字符後的小括號中的字符串取出,轉換爲int,而後+1後,再插入原位置。 最後返回StringBuffer的字符串形式。
*/
public static String countTypeChar(String str){
if(str == null)
return null;
if(str.isEmpty())
return "";
int len = str.length();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
//獲得c 在 sb 中的 位置
int index = sb.indexOf(Character.toString(c));
//c 已經存在sb 中了。那麼將原有的數量得到,並刪除,加1 以後插入回去。
if(index >=0 ){
//先得到sb 中c 的數量
//數量的起始索引,和結束索引
int start = index + 2;//當前字符的右邊的第二個符號
int end = sb.indexOf(")", start);
//得到當前字符的在sb 中 數量的值
int count = Integer.parseInt(sb.substring(start, end));
//刪除 數量 字符串
sb.delete(start, end);
//原有數量+1 插入回去
count ++;
sb.insert(start, Integer.toString(count));
}else{//不在sb 中 尾部添加 便可
sb.append(c+"(1)");
}
}
return sb.toString();
}
5、String類的 + 鏈接的實現
/**
* String 類的+ 鏈接實現
*
*/
public class TestStringBuffer1 {
public static void main(String[] args) {
String a = "a";
//直接指向常量池
String b = "a" + "b";
//變量 相加 或者是 變量和常量相加 底層使用StringBuilder 實現。
//在StringBuilder 沒有出來以前,使用StringBuffer 實現 + 鏈接。
String c = a + b + "a";
String str = new StringBuilder(a).append(b).append("a").toString();
}
}
6、字符串鏈接性能測試
public class TestStringConcat {
public static void main(String[] args) {
long time = System.currentTimeMillis();
for(int i=0;i<100000;i++){
concat6("rewrewrewfewrewfdwefewfrewfew", "32lkfjklwejrl2o3kdlemfrl243kj", "fjoweurolenmflkdnmvklsdnlkfew",
"fu98u798rjhoifdjiefldsfjdskljfvcd", "9123ljkrlemwfklmwe,.fm c,.dmv", "23oirjelkfmnkdslnmvkldsnmvdsklmnfds");
}
long cost = System.currentTimeMillis()-time;
System.out.println("cost = " + cost);
}
//210ms 會建立6個StringBuilder 對象
static String concat1(String s1,String s2,String s3,String s4,String s5,String s6){
String str = "";
str += s1;
str += s2;
str += s3;
str += s4;
str += s5;
str += s6;
return str;
}
//95 線程安全的,建立了一個StringBuffer 對象,存在屢次擴容的行爲
static String concat2(String s1,String s2,String s3,String s4,String s5,String s6){
StringBuffer sb = new StringBuffer();
sb.append(s1).append(s2).append(s3).append(s4).append(s5).append(s6);
return sb.toString();
}
//85 線程非安全的,建立了一個StringBuilder 對象,存在屢次擴容的行爲
static String concat3(String s1,String s2,String s3,String s4,String s5,String s6){
StringBuilder sb = new StringBuilder();
sb.append(s1).append(s2).append(s3).append(s4).append(s5).append(s6);
return sb.toString();
}
//62 建立了一個StringBuilder對象,存在屢次擴容
static String concat4(String s1,String s2,String s3,String s4,String s5,String s6){
return s1 + s2 + s3 + s4 + s5 + s6;
}
//67 建立一個StringBuffer 對象,不存在擴容行爲
static String concat5(String s1,String s2,String s3,String s4,String s5,String s6){
StringBuffer sb = new StringBuffer(s1.length()+s2.length() + s3.length() + s4.length() + s5.length() +s6.length());
sb.append(s1).append(s2).append(s3).append(s4).append(s5).append(s6);
return sb.toString();
}
//48 建立一個StringBuilder 對象,不存在擴容行爲
static String concat6(String s1,String s2,String s3,String s4,String s5,String s6){
StringBuilder sb = new StringBuilder(s1.length()+s2.length() + s3.length() + s4.length() + s5.length() +s6.length());
sb.append(s1).append(s2).append(s3).append(s4).append(s5).append(s6);
return sb.toString();
}
}
7、File
一個File對象既能夠表示一個文件,也能夠表示一個目錄。
提供了對文件對象和目錄對象的各類操做的方法。
對文件的操做:
建立文件
刪除文件
修改文件的屬性,不能修改文件的內容。
判斷是文件仍是目錄
獲得目錄下是全部的文件對象。
建立目錄,刪除目錄
判斷文件或者目錄是否存在
得到文件的絕對路徑。
得到文件的名字
重命名文件
......
絕對路徑:相對於盤符的路徑。
相對路徑:至關於當前工程根目錄。
例:
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestFile {
// 在相對路徑中建立1.txt 文件 工程目錄下
// 在c盤的根目錄下建立文件2.txt, 並修改其修改的時間 1970-05-20 13:14:20。
// 在c盤的根目錄下建立文件c:/7/7/2.txt
// 將指定的目錄下的,指定的後綴的文件所有刪除
// 使用遞歸將某個目錄下的全部的文件以及子目錄中的文件 文件的個數的統計。
// 使用遞歸實現,將指定的目錄以及其子目錄所有刪除。
public static void main(String[] args) {
// 從當前系統動態得到的路徑分隔符 和 目錄分隔符
System.out.println(File.pathSeparator);// ;
System.out.println(File.separator);// \
// deleteFilesBySuffix("c:\\class\\501", "class");
test2();
}
// 在res 的相對目錄中,建立 或者刪除指定的文件
static void test1() {
File file = new File("." + File.separator + "res" + File.separator
+ "1.txt");
if (file.exists()) {// 文件存在,刪除,
file.delete();
} else {// 不存在,建立新的
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 在c盤的根目錄下建立文件2.txt, 並修改其修改的時間 1970-05-20 13:14:20。
static void test2() {
File file = new File("F:\\2.txt");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
// 修改 time 要求是 距離 1970 年1月1日 的毫秒的時間差
try {
file.setLastModified(Long
.parseLong(dateToStamp("1970-05-20 13:14:20")));
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
// file.lastModified()
}
// 在c盤的根目錄下建立文件c:/7/7/2.txt
static void test3() {
File file = new File("c:\\88\\88");
// 先建立目錄
// file.mkdir() 只能建立一層
file.mkdirs();
// 再建立文件
File file2 = new File(file, "2.txt");
if (!file2.exists()) {
try {
file2.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*刪除指定目錄下的指定的後綴的文件
*
* @param path
* @param suffix
*/
static void deleteFilesBySuffix(String path, String suffix) {
File file = new File(path);
// 獲得當前目錄下的全部的文件
File[] files = file.listFiles();
// 遍歷全部的文件,若是文件的名字以suffix 結尾 就刪除
for (File file2 : files) {
// 得到文件的名字
String name = file2.getName();
if (name.endsWith(suffix)) {
file2.delete();
}
}
}
/*
* 將時間轉換爲時間戳
· public static String dateToStamp(String s) throws ParseException {
String res;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
Date date = simpleDateFormat.parse(s);
long ts = date.getTime();
res = String.valueOf(ts);
return res;
}
}