JDK9的新特性之String壓縮和字符編碼的實現(xiàn)方法
簡介
String的底層存儲是什么?相信大部分人都會說是數(shù)組。如果要是再問一句,那么是以什么數(shù)組來存儲呢?相信不同的人有不同的答案。
在JDK9之前,String的底層存儲結(jié)構(gòu)是char[],一個char需要占用兩個字節(jié)的存儲單位。
據(jù)說是JDK的開發(fā)人員經(jīng)過調(diào)研了成千上萬的應(yīng)用程序的heap dump信息,然后得出了一個結(jié)論:大部分的String都是以Latin-1字符編碼來表示的,只需要一個字節(jié)存儲就夠了,兩個字節(jié)完全是浪費。
據(jù)說他們用了大數(shù)據(jù)+人工智能,得出的結(jié)論由不得我們不信。
于是在JDK9之后,字符串的底層存儲變成了byte[]。
底層實現(xiàn)
先看下java9之前的String是怎么實現(xiàn)的:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
//The value is used for character storage.
private final char value[];
}
再看下java9中String的實現(xiàn)和一些關(guān)鍵的變量:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
@Stable
private final byte[] value;
private final byte coder;
@Native static final byte LATIN1 = 0;
@Native static final byte UTF16 = 1;
static final boolean COMPACT_STRINGS;
static {
COMPACT_STRINGS = true;
}
從代碼我們可以看到底層的存儲已經(jīng)變成了byte[]。
再看一下coder變量,coder代表編碼的格式,目前String支持兩種編碼格式LATIN1和UTF16。
LATIN1需要用一個字節(jié)來存儲。而UTF16需要使用2個字節(jié)或者4個字節(jié)來存儲。
而COMPACT_STRINGS則是用來控制是否開啟String的compact功能。默認(rèn)情況下COMPACT_STRINGS功能是開啟的。
如果我們想關(guān)閉COMPACT_STRINGS功能則可以使用-XX:-CompactStrings參數(shù)。
ps:下面看下jdk8日期格式化的實例代碼
package time;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
/***
* 總結(jié): java.util.Date和 SimpleDateFormat 都是非線程安全的
* 1. LocalDate
* 2. LocalTime
* 3. LocalDateTime
* 4. DateTimeFormatter
* 5. ChronoUnit
*/
public class Java8Date {
public static void main(String[] args) {
/** #0. Calendar
* 區(qū)別于calendar的month: canlendar中:[]
* 1. LocalDate的年月日直接是日期中的值;
* 2. date.getMonthValue() 和 c.get(Calendar.MONTH) 有區(qū)別: c:0表示1月
*/
Calendar c = Calendar.getInstance(); // 測試日期:2019-04-02
System.out.println(c.get(Calendar.YEAR)); // 2019
System.out.println(c.get(Calendar.MONTH)); // 3(0=1月)
System.out.println(c.get(Calendar.DAY_OF_MONTH)); //2
// #1. LocalDate 2019-04-02 : 今日日期: LocalDate.now()
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
LocalDate date = LocalDate.now();
System.out.println(date); // 2019-04-02
// #2. year month day: 年月日獲取
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
int year = date.getYear(); // 2019
int month = date.getMonthValue();// 4
int day = date.getDayOfMonth(); // 2
System.out.println(year + "-" + month + "-" + day); // 2019-4-2
// #3. 構(gòu)造日期: 給定年月日
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
LocalDate dt1 = LocalDate.of(2019, 3, 8);
LocalDate dt2 = LocalDate.of(2019, 3, 8);
// #4. 日期比較: equals
// true: 內(nèi)部是比較的 year-year month-month day-day
System.out.println(dt2.equals(dt1));
// #5. 周期性日期, 比如: 判斷用戶的生日
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
// 生日:0308
MonthDay uBirth = MonthDay.of(3, 8);
MonthDay dtMD = MonthDay.from(dt1);
// dt1 是不是 用戶u的生日:true
System.out.println("dt1==用戶u的生日:" + dtMD.equals(uBirth));
// #6. 獲取當(dāng)前時間 [HH:mm:ss.SSS]
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
LocalTime time = LocalTime.now();
System.out.println(time);
// #7. 增減時間 plus/minus
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
// dt1=2019-03-08
LocalDate dt1Plus2d = dt1.plusDays(2);
LocalDate dt1Plus2y = dt1.plusYears(2);
LocalDate dt1Plus2m = dt1.plusMonths(2);
System.out.println(dt1Plus2d); // 2019-03-10
System.out.println(dt1Plus2y); // 2021-03-08
System.out.println(dt1Plus2m); // 2019-05-08
// dt1=2019-03-08
LocalDate plus1w = dt1.plus(1, ChronoUnit.WEEKS);
LocalDate plus1d = dt1.plus(1, ChronoUnit.DAYS);
LocalDate plus18y = dt1.plus(18, ChronoUnit.YEARS);
LocalDate minus1y = dt1.minus(1, ChronoUnit.YEARS);
System.out.println(plus1w); // 2019-03-15
System.out.println(plus1d); // 2019-03-09
System.out.println(plus18y); // 2037-03-08
System.out.println(minus1y); // 2018-03-08
// #8. 日期dt1 早于/晚于 minus1y
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
// dt1=2019-03-08 minus1y=2018-03-08
System.out.println(dt1.isAfter(minus1y)); // true
System.out.println(dt1.isBefore(minus1y)); // false
// #9. 計算日期差
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
// dt1=2019-03-08 dt20190402
LocalDate dt20190402 = LocalDate.of(2019, 4, 2);
Period btPeriod = Period.between(dt1, dt20190402);
Period btPeriod2 = Period.between(dt1, dt20190402);
System.out.println(btPeriod); // P25D
System.out.println(btPeriod.getMonths()); // 0
System.out.println(btPeriod.getDays()); // 25
// 25 可見是標(biāo)量, 不是矢量, 只計算差數(shù)
System.out.println(btPeriod2.getDays());
// #10. 時間戳Instant->java.util.Date[getTime()==toEpochMilli()]
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
Instant now = Instant.now(); // 2019-04-02T08:48:46.755Z
Date dtNow = Date.from(now); // Tue Apr 02 16:48:46 CST 2019
long millisInstant = now.toEpochMilli();
long millisDate = dtNow.getTime();
System.out.println(millisInstant); // 1554195038598
System.out.println(millisDate); // 1554195038598
// #11# ** 日期格式化
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
DateTimeFormatter pattern1 = DateTimeFormatter.ofPattern("yyyyMMdd-HH:mm:ss,SSS");
DateTimeFormatter pattern2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/**
* 命題:--> 將 "20190215-22:10:30,333" 日期
* 格式化為 "yyyyMMdd-HH mm:ss.SSS" 字符串
* @.1. 字符串轉(zhuǎn)對象LocalDateTime
* @.2. LocalDateTime對象轉(zhuǎn)字符串
*/
String strDt = "20190215-22:10:30,333"; // @.1.
LocalDateTime dateTime = LocalDateTime.parse(strDt, pattern1);
String fmtDtString = dateTime.format(pattern2); // @.2.
System.out.println(dateTime); // 2019-02-15T22:10:30.333
System.out.println(fmtDtString); // 2019-02-15 22:10:30
System.out.println("=-==-==-==-==-==-==-==-==-==-==");
}
}
總結(jié)
本文講解了新的String實現(xiàn)和COMPACT_STRINGS模式的關(guān)閉方法。
到此這篇關(guān)于JDK9的新特性之String壓縮和字符編碼的實現(xiàn)方法的文章就介紹到這了,更多相關(guān)JDK9 新特性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實現(xiàn)兩人五子棋游戲(五) 判斷是否有一方勝出
這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)兩人五子棋游戲,判斷是否有一方勝出,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03
SpringBoot線程池和Java線程池的使用和實現(xiàn)原理解析
這篇文章主要介紹了SpringBoot線程池和Java線程池的用法和實現(xiàn)原理,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04
多模塊maven的deploy集成gitlab?ci自動發(fā)版配置
這篇文章主要為大家介紹了多模塊maven項目deploy集成gitlab?ci自動發(fā)版的配置流程步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02
maven坐標(biāo)Dependencies和Exclusions的使用
這篇文章主要介紹了maven坐標(biāo)Dependencies和Exclusions的使用,很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12

