注: 拉钩教育大数据训练营java基础模块三之java类库笔记 + 补充
Jdk11
Integer
建议 Integer.valueOf() 创建; Integer-》int : intValue();
Q: BigInteger Integer String 的底层源码分析
String
String类的常用方法 static valueOf() trime, toUpperCase(); toLowerCase(); contains(Character s);内部调用indexof(s.toString()) startWith();endsWith() substring(int i);substring(int i ,int j);不包含【j】 split(); match(); replace(char a, char b); replaceFirst (String source,String targer); replaceAll(String source,String targer);
正则表达式
StringBuilder
继承于
abstract class AbstractStringBuilder implements Appendable, CharSequence
byte [] value;
存储数据的数组,The value is used for character storage 注:JDK 8 为 char [] value
byte coder;
The id of the encoding used to encode the bytes in {@code value}.
int count;
The count is the number of characters used.
初始化与append操作
StringBuilder a = new StringBuilder();
初始化ade调用过程:初始化一个长度为16的value数组。调用super(16),其中a.length()为0,a.capacity()为16;因为capacity()返回的是数组value的大小,而length()返回的是数组中有多少数据。
StringBuilder b = new StringBuilder("hello");
初始化b时过程调用过程:super("hello".length + 16);append("str"); 而 StringingBuilder 成员方法 append(String str) 是调用其父类AbstractStringBuilder的方法。
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);//检查value在添加str后是否要扩容
/*
如果count+len > value.length 就得扩容,否则什么都不做;
扩容value = Arrays.copyOf(value,newCapacity(minimumCapacity));
将旧数组value的数据复制到扩容后的新数组上,并重新引用该新数组。
*/
//jdk 1.8
str.getChars(0, len, value, count);//简单理解就是在value数组后面添加str
/*String对象的成员方法,这里的value是String中的数组value
getchars(int srcBegin, int srcEnd, char dst[], int dstBegin)
把下标从srcBegin到srcEnd的字符片段 复制 到下标为dstBegin开始的dst数组中。
底层调用了
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
*/
//jdk 11
putStringAt(count, str);
count += len;//添加str后数组数据长度刷新
return this;
}
AbstractStringBuilder 的扩容机制 int newCapacity(minimumCapacity)源代码剖析:
newCapacity为原数组长度增大一倍后再加2,再比较它与minCapacity取它们的最大值,再判断下newCapacity是否超过了MAX_ARRAY_SIZE限制的大小,如果超过了且没有大于Integer.MAX_VALUE 或者 newCapacity 一开始便小于 MAX_ARRAY_SIZE的话,就返回新数组容量数值newCapacity;如果超过了Integer.MAX_VALUE就抛内存容量超出异常。
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
private int hugeCapacity(int minCapacity) {
if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE)
? minCapacity : MAX_ARRAY_SIZE;
}
这里有个疑问:为什么有个MAX_ARRAY_SIZE限制,为什么不直接比较Integer.MAX_VALUE
源代码中如下,大致意思是除非有需要数组的最大容量应该留出点空间给虚拟机VM存储一些头部文件信息,任何要分配跟大容量数组的行为都可能会导致虚拟机内存不足异常。
- 什么是虚拟机头部文件呢? 后面补坑
/**
* The maximum size of array to allocate (unless necessary).
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
StringBuilder 的 insert()与delete()
StringBuilder继承了父类的插入删除操作,insert()核心的两个重载方法是
//从offset开始添加str
//如果不需要扩容,就将数组向右偏移len个长度单位,再复制新字符串到偏移位置
public AbstractStringBuilder insert(int offset, String str){
if ((offset < 0) || (offset > length()))
throw new StringIndexOutOfBoundsException(offset);
if (str == null)
str = "null";
int len = str.length();
ensureCapacityInternal(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset);
str.getChars(value, offset);
count += len;
return this;
}
//从index开始 添加字符str片段,其中字符片段以offset开始 长度为len
public AbstractStringBuilder insert(int index, char[] str, int offset,int len){
...
System.arraycopy(value, index, value, index + len, count - index);
System.arraycopy(str, offset, value, index, len);
...
}
删除操作
//从start删除到end,但不包括下标哪个元素
//因为底层调用的是System.arraycopy(),没有真正内存的删除,
//而是将value数组end位置起到(count-1)位置这些元素 拷贝到 start 开始的地方。
public AbstractStringBuilder delete(int start, int end){
...
...
int len = end - start;
if (len > 0) {
System.arraycopy(value, start+len, value, start, count-end);
count -= len;
}
}
//同上理调用System.arraycopy()方法
public AbstractStringBuilder deleteCharAt(int index){
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
System.arraycopy(value, index+1, value, index, count-index-1);
count--;
return this;
}
jdk11 版本
public AbstractStringBuilder delete(int start, int end) {
int count = this.count;
if (end > count) {
end = count;
}
checkRangeSIOOBE(start, end, count);
int len = end - start;
if (len > 0) {
shift(end, -len);
this.count = count - len;
}
return this;
}
private void shift(int offset, int n) {
System.arraycopy(value, offset << coder,
value, (offset + n) << coder, (count - offset) << coder);
}
反转和查找
public AbstractStringBuilder reverse() {
byte[] val = this.value;
int count = this.count;
int coder = this.coder;
int n = count - 1;
if (COMPACT_STRINGS && coder == LATIN1) {
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
byte cj = val[j];
val[j] = val[k];
val[k] = cj;
}
} else {
StringUTF16.reverse(val, count);
}
return this;
}
public AbstractStringBuilder replace(int start, int end, String str) {
int count = this.count;
if (end > count) {
end = count;
}
checkRangeSIOOBE(start, end, count);
int len = str.length();
int newCount = count + len - (end - start);
ensureCapacityInternal(newCount);
shift(end, newCount - count);
this.count = newCount;
putStringAt(start, str);
return this;
}
StringUTF16 和 StringLatin1 以及 jdk11 中String 有关byte和字符的新特性 日后补充
日期类
Date a = new Date() 已过时
SimpleDateFormat 设置时间格式 “yy-MM-dd HH-mm-ss”
Calender类
- java.util.Calender类主要用于描述特定的瞬间,取代Date类中的过时方法实现全球化。 该类是个抽象类,因此不能实例化对象,其具体子类针对不同国家的日历系统,其中应用最广泛的是GregorianCalendar(格里高利历),对应世界上绝大多数国家/地区使用的标准日历系统
多态三种方式
- 通过方法的参数传递形成多态; public static void draw(Shape s){ s.show(); } draw(new Rect(1, 2, 3, 4));
- 在方法体中直接使用多态的语法格式 Account acc = new FixedAccount();
- 通过方法的返回值类型形成多态 Calender getInstance(){ return new GregorianCalendar(zone, aLocale); }
缺点:Date类中的年份是从1900开始的,而月份都从0开始。 格式化只对Date类有用,对Calendar类则不能使用。 非线程安全等。
JAVA8 日期类
LockDate LockTime LockDateTime(常用)
- 获取年份字段的数值 int getYear()
- 设置为参数指定的年 LocalDateTime withYear(int year)
- 加上参数指定的年 LocalDateTime plusYears(long years)
- 减去参数指定的年 LocalDateTime minusYears(long years) 年月日时分秒 的各种方法同上
Instant类
- static Instant now() 从系统时钟上获取当前时间
- OffsetDateTimeatOffset(ZoneOffset offset) 将此瞬间与偏移量组合以创建偏移日期时间
- static Instant ofEpochMilli(long epochMilli) 根据参数指定的毫秒数来构造对象,参数为距离1970年1月1 日0时0分0秒的毫秒数
- long toEpochMilli() 获取距离1970年1月1日0时0分0秒的毫秒数
DateFormatter类
- static DateTimeFormatter ofPattern(String pattern) 根据参数指定的模式来获取对象
- String format(TemporalAccessor temporal) 将参数指定日期时间转换为字符串
- TemporalAccessor parse(CharSequence text) 将参数指定字符串转换为日期时间
LocalDateTime dd = LocalDateTime.now();
DateTimeFormatter ff = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String string = ff.format(dd);
System.out.println(string);
TemporalAccessor par = ff.parse(string);
System.out.println(par);
集合
源码分析
日后补坑