BitSet源码
public class BitSet1 implements Cloneable, java.io.Serializable {
// >>>左边补0, << 右边补0。
public final static int ADDRESS_BITS_PER_WORD = 6;
public final static int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;//2^6=64
public final static int BIT_INDEX_MASK = BITS_PER_WORD - 1;//
public static final long WORD_MASK = 0xffffffffffffffffL;//16进制64bit,全1,就是-1 //序列化字段,第i位存储在位位置i%64的位[i/64]中
public static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("bits", long[].class),
}; public long[] words;//long数组来作为内部存储结构。Bitset至少为一个long的大小 //数组长度
public transient int wordsInUse = 0;//使用的words数组,小于等于words.length。wordsInUse-1是不为0的long的最大位置。一直到words.length可以等于0。 //“words”的大小是否由用户指定。
public transient boolean sizeIsSticky = false; public static final long serialVersionUID = 7997698588986878753L; public static int wordIndex(int bitIndex) {
return bitIndex >> ADDRESS_BITS_PER_WORD;//除以64,右移6位,取整。
//1-6位全部移出去,第6位=32移出去了变成了0。第7位=64变成第一位=1,第8位=128变成第二位=2。从第7位到32位全部除以64,不要余数取整。
} //wordsInUse >= 0 , wordsInUse <= words.length , words[wordsInUse - 1] != 0 , words[wordsInUse] == 0
public void checkInvariants() {
//左边走了,右边就不走了。
assert(wordsInUse >= 0 && wordsInUse <= words.length);
assert(wordsInUse == 0 || words[wordsInUse - 1] != 0);
//wordsInUse等于0可以,就不走右边了。不等于0那么words[wordsInUse - 1]就不能为0。wordsInUse-1是不为0的long的最大位置。
assert(wordsInUse == words.length || words[wordsInUse] == 0);
//wordsInUse == words.length可以就不走右边了。如果2者不相等wordsInUse要小,words[wordsInUse]就要等于0。words[wordsInUse - 1]就不能为0。
} //清除为0的,减少内存。
public void recalculateWordsInUse() {
int i;
for (i = wordsInUse-1; i >= 0; i--)
if (words[i] != 0)
break;
wordsInUse = i+1; // 从后往前找,第一个非0的后面一个元素
} public BitSet1() {
initWords(BITS_PER_WORD);//64长度,words数组只有1个长度。
sizeIsSticky = false;//为false表示使用的是默认大小
} public BitSet1(int nbits) {
if (nbits < 0)
throw new NegativeArraySizeException("nbits < 0: " + nbits);
initWords(nbits);//传进来的是bit位的位数
sizeIsSticky = true;//为true表示大小是传进来的
} public void initWords(int nbits) {//nbits是总位数,一个long是64位。
words = new long[wordIndex(nbits-1) + 1];//wordIndex是取整
} public BitSet1(long[] words) {
this.words = words;//[113, 289, 8481]
this.wordsInUse = words.length;//>=0,3
checkInvariants();
} //BitSet.valueOf(longs).get(n) == ((longs[n/64] & (1L<<(n%64))) != 0) for all n < 64 * longs.length .
public static BitSet1 valueOf(long[] longs) {
int n;//都要先除去0的元素,节约内存。
for (n = longs.length; n > 0 && longs[n - 1] == 0; n--);//n-1是longs数组最后一个不为0的索引位置,n就是个数。
return new BitSet1(Arrays.copyOf(longs, n));//拷贝longs前n个元素或者longs数组长度个元素,取2者较小者。
} //把lb中真实元素(position到limit),并且去除多余的0,然后给bitset。
public static BitSet1 valueOf(LongBuffer1 lb) {//LongBuffer是提供对long[]数组操作。对于读取到的long[]做一些增删改查后再使用,就是缓冲区。
//mark=-1,pos=0,lim=limit-position,cap=limit-position,offset=position。 slice()得到的是原来position到limit的位置的数据,包括position不包括limit。所有元素相对原来数组的相对值是offset,
//从0开始一直到remaining()。
lb = lb.slice();
int n;
//确定最后一个不为0的数据的个数。都要先除去0的元素,节约内存。
//slice()之后的put和set都会加上offset=pisition,就是获取原数组的position到limit的所有位置元素,不包括limit。
for (n = lb.remaining(); n > 0 && lb.get(n - 1) == 0; n--);//从0开始一直到remaining(),除去后面为0的。
long[] words = new long[n];//n是不为0的位置个数,包括开头一共n个,
lb.get(words);//把lb的值全部复制到words里面去。
return new BitSet1(words);
} public static BitSet1 valueOf(byte[] bytes) {
return BitSet1.valueOf(ByteBuffer.wrap(bytes));
} //把bb中真实元素(position到limit),并且去除多余的0,然后给bitset。
public static BitSet1 valueOf(ByteBuffer bb) {
bb = bb.slice().order(ByteOrder.LITTLE_ENDIAN);//slice()之后,所有元素相对原来数组的相对值是offset,从0到remaining。
int n;
for (n = bb.remaining(); n > 0 && bb.get(n - 1) == 0; n--);//除去0重新计算n = position到limit除去0之后元素个数。
long[] words = new long[(n + 7) / 8];//取整加1
bb.limit(n);//bb的limit之前等于remainnig,现在为n。
int i = 0;
while (bb.remaining() >= 8)
words[i++] = bb.getLong();//position移动8位,
for (int remaining = bb.remaining(), j = 0; j < remaining; j++)
words[i] |= (bb.get() & 0xffL) << (8 * j);//0xffL:前面全0,后面一个字节8个1。移8n位再或。
return new BitSet1(words);
} /*
byte[] bytes = s.toByteArray();
bytes.length == (s.length()+7)/8 and s.get(n) == ((bytes[n/8] & (1<<(n%8))) != 0):实例画图。
*/
public byte[] toByteArray() {//bit是从long数组低位开始放,一直放到最高位,最高位是从低位开始放。
int n = wordsInUse;
if (n == 0)
return new byte[0];
int len = 8 * (n-1);
for (long x = words[n - 1]; x != 0; x >>>= 8)//最后一个的值,一直除以256,
len++;
byte[] bytes = new byte[len];
ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
for (int i = 0; i < n - 1; i++)
bb.putLong(words[i]);
for (long x = words[n - 1]; x != 0; x >>>= 8)
bb.put((byte) (x & 0xff));
return bytes;
} public long[] toLongArray() {
return Arrays.copyOf(words, wordsInUse);
} public void ensureCapacity(int wordsRequired) {
if (words.length < wordsRequired) {
int request = Math.max(2 * words.length, wordsRequired);
words = Arrays.copyOf(words, request);//长度还是request个长度,只是复制 Math.min(words.length, request)元素过去。
sizeIsSticky = false;
}
} public void expandTo(int wordIndex) {
int wordsRequired = wordIndex+1;
if (wordsInUse < wordsRequired) {
ensureCapacity(wordsRequired);
wordsInUse = wordsRequired;
}
} public static void checkRange(int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
if (toIndex < 0)
throw new IndexOutOfBoundsException("toIndex < 0: " + toIndex);
if (fromIndex > toIndex)
throw new IndexOutOfBoundsException("fromIndex: " + fromIndex + " > toIndex: " + toIndex);
} public void flip(int bitIndex) {//65,指定位反转。
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int wordIndex = wordIndex(bitIndex);//
expandTo(wordIndex);
words[wordIndex] ^= (1L << bitIndex);//移动位数对64取模,异或就是其余位置不变,这个位置取反。
recalculateWordsInUse();
checkInvariants();
} public void flip(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
if (fromIndex == toIndex)
return;
int startWordIndex = wordIndex(fromIndex);//开始数组索引
int endWordIndex = wordIndex(toIndex - 1);//结束数组索引,要减1。
expandTo(endWordIndex);
//fromIndex对64取模位置开始(包括这个位置)一直到最前面都是1,后面都是0。
long firstWordMask = WORD_MASK << fromIndex;//用于异或的值
//>>>左边补上0,左边是0右边是1。右移64-toIndex%64
//6>>>-2相当于6>>>30,(32+(-2))==30。
long lastWordMask = WORD_MASK >>> -toIndex;//无符号右移,忽略了符号位扩展,0补左边。用于异或的值
if (startWordIndex == endWordIndex) {
// 一个数组里面异或
words[startWordIndex] ^= (firstWordMask & lastWordMask);//对1异或,就是取反。
} else {
// 开始数组异或
words[startWordIndex] ^= firstWordMask;
// 中间数组异或
for (int i = startWordIndex+1; i < endWordIndex; i++)
words[i] ^= WORD_MASK;
// 结尾数组异或
words[endWordIndex] ^= lastWordMask;
}
recalculateWordsInUse();
checkInvariants();
} public void set(int bitIndex) {//设置bit位为1
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int wordIndex = wordIndex(bitIndex);
expandTo(wordIndex);
words[wordIndex] |= (1L << bitIndex);
checkInvariants();
} public void set(int bitIndex, boolean value) {
if (value)
set(bitIndex);
else
clear(bitIndex);
} public void set(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
if (fromIndex == toIndex)
return;
int startWordIndex = wordIndex(fromIndex);
int endWordIndex = wordIndex(toIndex - 1);
expandTo(endWordIndex);
long firstWordMask = WORD_MASK << fromIndex;
long lastWordMask = WORD_MASK >>> -toIndex;
if (startWordIndex == endWordIndex) {
words[startWordIndex] |= (firstWordMask & lastWordMask);//0变成1,1变成1,就是全设置为1。
} else {
words[startWordIndex] |= firstWordMask;//或操作就是设置为1,
for (int i = startWordIndex+1; i < endWordIndex; i++)
words[i] = WORD_MASK;
words[endWordIndex] |= lastWordMask;
}
checkInvariants();
} public void set(int fromIndex, int toIndex, boolean value) {
if (value)
set(fromIndex, toIndex);
else
clear(fromIndex, toIndex);
} public void clear(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int wordIndex = wordIndex(bitIndex);
if (wordIndex >= wordsInUse)
return;
words[wordIndex] &= ~(1L << bitIndex);//指定位变为0,&是与操作,1L<<n是只有1位的long值。
recalculateWordsInUse();
checkInvariants();
} public void clear(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
if (fromIndex == toIndex)
return;
int startWordIndex = wordIndex(fromIndex);
if (startWordIndex >= wordsInUse)
return;
int endWordIndex = wordIndex(toIndex - 1);
if (endWordIndex >= wordsInUse) {
toIndex = length();
endWordIndex = wordsInUse - 1;
}
long firstWordMask = WORD_MASK << fromIndex;
long lastWordMask = WORD_MASK >>> -toIndex;
if (startWordIndex == endWordIndex) {
words[startWordIndex] &= ~(firstWordMask & lastWordMask);//
} else {
words[startWordIndex] &= ~firstWordMask;
for (int i = startWordIndex+1; i < endWordIndex; i++)
words[i] = 0;
words[endWordIndex] &= ~lastWordMask;
}
recalculateWordsInUse();
checkInvariants();
} public void clear() {
while (wordsInUse > 0)
words[--wordsInUse] = 0;//全部清0
} public boolean get(int bitIndex) {//返回的0,1就是true,false。
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
checkInvariants();
int wordIndex = wordIndex(bitIndex);
//通过与操作得到一个long的值,来判断某一位是0还是1。
//&就能按位操作
//1L << bitIndex就能得到移位后的long值
return (wordIndex < wordsInUse) && ((words[wordIndex] & (1L << bitIndex)) != 0);
} public BitSet1 get(int fromIndex, int toIndex) {//包头不包尾,获取指定区间的bitset,返回的也是long[]数组装着。
checkRange(fromIndex, toIndex);
checkInvariants();
int len = length();//总共多少bit位
if (len <= fromIndex || fromIndex == toIndex)
return new BitSet1(0);
if (toIndex > len)
toIndex = len;
BitSet1 result = new BitSet1(toIndex - fromIndex);//bit的长度
//toIndex - fromIndex:::0-64:1,65-128:2,129-192:3。
int targetWords = wordIndex(toIndex - fromIndex - 1) + 1;//数组个数
int sourceIndex = wordIndex(fromIndex);//开始数组索引
//对64取余为0,开始位置就是64的整数倍0,64,128,192。
boolean wordAligned = ((fromIndex & BIT_INDEX_MASK) == 0); //除了最后一个word。为数组前n-1个元素赋值
for (int i = 0; i < targetWords - 1; i++, sourceIndex++)
result.words[i] = wordAligned ? words[sourceIndex] : //开始位置是64整数倍,整个long拿出去
(words[sourceIndex] >>> fromIndex) | (words[sourceIndex+1] << -fromIndex);//数组相邻位置凑成64个。从左边fromIndex位置到右边fromIndex位置取出64个来成为一个long,包括左边fromIndex不包括右边fromIndex。
//一直到最后一个的fromIndex的位置(最后一个fromIndex还没有取出去),并且最后一个的fromIndex到toIndex构成不了64个。 long lastWordMask = WORD_MASK >>> -toIndex; //WORD_MASK = 0xffffffffffffffffL。toIndex右边都是1(不包括toIndex)。
result.words[targetWords - 1] =
//64取余,一个数组里面谁在左边右边。
//toIndex-1 < fromIndex,fromIndex取余后要大,由于是反的,fromIndex在左边toIndex-1在右边。所以有2个long元素综合起来。
((toIndex-1) & BIT_INDEX_MASK) < (fromIndex & BIT_INDEX_MASK)//BIT_INDEX_MASK=63。
?
((words[sourceIndex] >>> fromIndex) | //最后一个没有取完的,
(words[sourceIndex+1] & lastWordMask) << -fromIndex)//加上toIndex右边的,
:
((words[sourceIndex] & lastWordMask) >>> fromIndex);//toIndex-1 > fromIndex,toIndex在左边, result.wordsInUse = targetWords;
result.recalculateWordsInUse();
result.checkInvariants(); return result;
} public int nextSetBit(int fromIndex) {//从fromIndex开始第一个1在哪个位置(包括fromIndex),返回的位置是索引,
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
checkInvariants();
int u = wordIndex(fromIndex);
if (u >= wordsInUse)
return -1;
long word = words[u] & (WORD_MASK << fromIndex);//words[u]左边fromIndex(取模)开始为1(包括fromIndex位置)。fromIndex右边要置为0。
System.out.println(Long.toBinaryString(word));
System.out.println(Long.toBinaryString(WORD_MASK << fromIndex));
while (true) {
if (word != 0) {//等于0就全是0,
System.out.println(Long.numberOfTrailingZeros(word));
return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);//numberOfTrailingZeros右边有多少个0,
}
if (++u == wordsInUse)//u加1一直到wordsInUse-1,就退出
return -1;
word = words[u];//修改word的值,不移位了。
}
} public int nextClearBit(int fromIndex) {//从fromIndex开始第一个为0的位置,包括fromIndex。返回的位置是索引,
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
checkInvariants();
int u = wordIndex(fromIndex);
if (u >= wordsInUse)
return fromIndex; long word = ~words[u] & (WORD_MASK << fromIndex); while (true) {
if (word != 0)
return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);//numberOfTrailingZeros右边有多少个0,
//word全1就++,
if (++u == wordsInUse)
return wordsInUse * BITS_PER_WORD;
word = ~words[u];
}
} public int previousSetBit(int fromIndex) {//从fromIndex开始(包括fromIndex)前面第一个1,
if (fromIndex < 0) {
if (fromIndex == -1)
return -1;
throw new IndexOutOfBoundsException("fromIndex < -1: " + fromIndex);
}
checkInvariants();
int u = wordIndex(fromIndex);
if (u >= wordsInUse)
return length() - 1;
long word = words[u] & (WORD_MASK >>> -(fromIndex+1));//fromIndex到右都是1,包括fromIndex,
while (true) {
if (word != 0)
return (u+1) * BITS_PER_WORD - 1 - Long.numberOfLeadingZeros(word);//左边有多少个0
if (u-- == 0)
return -1;
word = words[u];
}
} public int previousClearBit(int fromIndex) {
if (fromIndex < 0) {
if (fromIndex == -1)
return -1;
throw new IndexOutOfBoundsException("fromIndex < -1: " + fromIndex);
}
checkInvariants();
int u = wordIndex(fromIndex);
if (u >= wordsInUse)
return fromIndex;
long word = ~words[u] & (WORD_MASK >>> -(fromIndex+1));
while (true) {
if (word != 0)
return (u+1) * BITS_PER_WORD -1 - Long.numberOfLeadingZeros(word);
if (u-- == 0)
return -1;
word = ~words[u];
}
} public int length() {
if (wordsInUse == 0)
return 0;
return BITS_PER_WORD * (wordsInUse - 1) + //前面64*(length-1)个位的个数
//numberOfLeadingZeros()一个long值里面左边有多少个0,
(BITS_PER_WORD - Long.numberOfLeadingZeros(words[wordsInUse - 1]));
} public boolean isEmpty() {
return wordsInUse == 0;
} public boolean intersects(BitSet1 set) {
for (int i = Math.min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--)
if ((words[i] & set.words[i]) != 0)//&是位操作,等于0就继续,等于0就是没有1跟1相对的。
return true;
return false;
} public int cardinality() {
int sum = 0;
for (int i = 0; i < wordsInUse; i++)
sum += Long.bitCount(words[i]);//为1的个数
return sum;
} public void and(BitSet1 set) {
if (this == set)
return;
while (wordsInUse > set.wordsInUse)
words[--wordsInUse] = 0;
for (int i = 0; i < wordsInUse; i++)
words[i] &= set.words[i];//逻辑与操作
recalculateWordsInUse();
checkInvariants();
} public void or(BitSet1 set) {//逻辑或操作
if (this == set)
return;
int wordsInCommon = Math.min(wordsInUse, set.wordsInUse);
if (wordsInUse < set.wordsInUse) {
ensureCapacity(set.wordsInUse);
wordsInUse = set.wordsInUse;
}
for (int i = 0; i < wordsInCommon; i++)
words[i] |= set.words[i];
if (wordsInCommon < set.wordsInUse)
System.arraycopy(set.words, wordsInCommon, words, wordsInCommon, wordsInUse - wordsInCommon);
checkInvariants();
} public void xor(BitSet1 set) {
int wordsInCommon = Math.min(wordsInUse, set.wordsInUse);
if (wordsInUse < set.wordsInUse) {
ensureCapacity(set.wordsInUse);
wordsInUse = set.wordsInUse;
}
for (int i = 0; i < wordsInCommon; i++)
words[i] ^= set.words[i];
if (wordsInCommon < set.wordsInUse)
System.arraycopy(set.words, wordsInCommon, words, wordsInCommon, set.wordsInUse - wordsInCommon); recalculateWordsInUse();
checkInvariants();
} public void andNot(BitSet1 set) {// Perform logical (a & !b) on words in common
for (int i = Math.min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--)
words[i] &= ~set.words[i];
recalculateWordsInUse();
checkInvariants();
} public int hashCode() {
long h = 1234;
for (int i = wordsInUse; --i >= 0; )
h ^= words[i] * (i + 1);
return (int)((h >> 32) ^ h);
} public int size() {
return words.length * BITS_PER_WORD;
} public boolean equals(Object obj) {
if (!(obj instanceof BitSet1))
return false;
if (this == obj)
return true;
BitSet1 set = (BitSet1) obj;
checkInvariants();
set.checkInvariants();
if (wordsInUse != set.wordsInUse)
return false;
for (int i = 0; i < wordsInUse; i++)
if (words[i] != set.words[i])
return false;
return true;
} public Object clone() {
if (! sizeIsSticky)
trimToSize();
try {
BitSet1 result = (BitSet1) super.clone();
result.words = words.clone();
result.checkInvariants();
return result;
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
} public void trimToSize() {
if (wordsInUse != words.length) {
words = Arrays.copyOf(words, wordsInUse);//只要wordsInUse和words.length较小者
checkInvariants();
}
} public void writeObject(ObjectOutputStream s) throws IOException {
checkInvariants();
if (! sizeIsSticky)
trimToSize();
ObjectOutputStream.PutField fields = s.putFields();
fields.put("bits", words);
s.writeFields();
} public void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
words = (long[]) fields.get("bits", null);
// Assume maximum length then find real length
// because recalculateWordsInUse assumes maintenance
// or reduction in logical size
wordsInUse = words.length;
recalculateWordsInUse();
sizeIsSticky = (words.length > 0 && words[words.length-1] == 0L); // heuristic
checkInvariants();
} public String toString() {//所有的1的索引位置,{0, 4, 5, 6, 64, 69, 72, 128, 133, 136, 141}
checkInvariants();
//大于128就看1的个数,小于就看所有个数
int numBits = (wordsInUse > 128) ? cardinality() : wordsInUse * BITS_PER_WORD;
StringBuilder b = new StringBuilder(6*numBits + 2);//
b.append('{');
int i = nextSetBit(0);//从0开始的第一个1在哪个位置,
System.out.println("i1="+i);
if (i != -1) {
b.append(i);//i是所有的1的索引位置,
System.out.println("b="+b);
while (true) {
if (++i < 0) break;//超过int最大值,前面i已经加过一次了,这里直接加加,
if ((i = nextSetBit(i)) < 0) break;//从i+1开始,下一个为1的位置在哪里,
int endOfRun = nextClearBit(i);//这里的i是还没有加进去的1的位置,
System.out.println("endOfRun="+endOfRun);//从还没有加进去的i的位置开始,0的位置。
System.out.println("i2="+i);
do {
b.append(", ").append(i); //把这个i放入string里面,然后下面在加加,
System.out.println("b="+b);//中间全是1都加进去到b,
}while (++i != endOfRun);//跳出时候i是0的位置endOfRun,所以出去后要加1, }
}
b.append('}');
return b.toString();
} /**
* Returns a stream of indices for which this BitSet
* contains a bit in the set state. The indices are returned
* in order, from lowest to highest. The size of the stream
* is the number of bits in the set state, equal to the value
* returned by the {@link #cardinality()} method.
*
* <p>The bit set must remain constant during the execution of the
* terminal stream operation. Otherwise, the result of the terminal
* stream operation is undefined.
*/
public IntStream stream() {
class BitSetIterator implements PrimitiveIterator.OfInt {
int next = nextSetBit(0);//从0开始的第一个1的位置,
@Override
public boolean hasNext() {
return next != -1;
}
@Override
public int nextInt() {
if (next != -1) {
int ret = next;
next = nextSetBit(next+1);//下一个1的位置
return ret;
} else {
throw new NoSuchElementException();
}
}
} return StreamSupport.intStream(
//spliterator返回IntIteratorSpliterator分组器
() -> Spliterators.spliterator(new BitSetIterator(), cardinality(),Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED),
Spliterator.SIZED | Spliterator.SUBSIZED |Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED,false);
}
}
BitSet源码的更多相关文章
- JDK中的BitMap实现之BitSet源码分析
前提 本文主要内容是分析JDK中的BitMap实现之java.util.BitSet的源码实现,基于JDK11编写,其他版本的JDK不一定合适. 文中的图比特低位实际应该是在右边,但是为了提高阅读体验 ...
- Java数据结构: java.util.BitSet源码学习
接着上一篇Blog:一道面试题与Java位操作 和 BitSet 库的使用,分析下Java源码中BitSet类的源码. 位图(Bitmap),即位(Bit)的集合,是一种常用的数据结构,可用于记录大量 ...
- Servlet-Cookie源码分析 源码环境:Tomcat8
最近在学习servlet的一些实现细节,阅读了Cookie的源码. Cookie本质上是服务器发送给客户端(主要是浏览器)的一个会话临时数据. 其源码注释文档的说明: Creates a cookie ...
- java源码学习(四)ArrayList
ArrayList ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下, ...
- PHP源码阅读strtr
strtr 转换字符串中特定的字符,但是这个函数使用的方式多种. echo strtr('hello world', 'hw', 'ab'); // 第一种 aello borld echo strt ...
- ArrayList源码解析(JDK1.8)
package java.util; import sun.misc.SharedSecrets; import java.util.function.Consumer; import java.ut ...
- Stack和Vector源码分析
Stack和Vector源码分析 Stack和Vector源码分析stack源码分析1.Stack是什么2.Stack的结构图3.Stack继承关系4.Stack的主要方法5.Stack源码Vecto ...
- ArrayList源码分析超详细
ArrayList源码分析超详解 想要分析下源码是件好事,但是如何去进行分析呢?以我的例子来说,我进行源码分析的过程如下几步: 找到类:利用 IDEA 找到所需要分析的类(ztrl+N查找ArraLi ...
- 集合源码分析[3]-ArrayList 源码分析
历史文章: Collection 源码分析 AbstractList 源码分析 介绍 ArrayList是一个数组队列,相当于动态数组,与Java的数组对比,他的容量可以动态改变. 继承关系 Arra ...
随机推荐
- Console程序下监控EFCore生成的SQL语句!
最近这两天在使用控制台程序学习EFCore,突然想看看生成的SQL语句,所以在网上找到一位大神的分享的方法! 准备工作: 1). MySqlEFCore NuGet: Pomelo.EntityF ...
- mvc控制器接收ajax传送的数据
视图层中ajax传数据 $.ajax({ type: "post",//提交方式 data: { complay_arry: complay_arry, site_arry: si ...
- localdb启动
前提:vs自带localdb,不用另外装.其次,vs里的的“sql server 对象资源管理器”(在视图里)可以常规管理它.相比之下,SSMS更专业(推荐),按情况选用. 正文: 安装完毕后…… C ...
- SQL查询数据库中所有表、表字段名及数据类型
select b.name,a.colid,a.name ,())+')' from systypes where a.xusertype=systypes.xusertype ) type from ...
- vue自学笔记
做前端也做了一段时间了,为了高薪,不能一直做网页不是~~,所以从今天开始整理vue的笔记 内容都是从网上搜集整合并且自己实践过了的,需要注意的点,也在后面标注了“注” 当然了,如果有什么问题的 ...
- Android中H5和Native交互的两种方式
Android中H5和Native交互的两种方式:http://www.jianshu.com/p/bcb5d8582d92 注意事项: 1.android给h5页面注入一个对象(WZApp),这个对 ...
- Fundebug前端JavaScript插件更新至1.8.0,兼容低版本的Android浏览器
摘要: 兼容低版本Android浏览器,请大家及时更新. Fundebug前端BUG监控服务 Fundebug是专业的程序BUG监控平台,我们JavaScript插件可以提供全方位的BUG监控,可以帮 ...
- ETHINK组件取值手册
Ethink组件取值手册 一.取值 Sql查询配置中取值方式:所有可以对外过滤的组件都可以用id.output取值 就是取组件setOutput()里输出的值 ,具体分为以下两种: 1)$p{OBJ_ ...
- MySQL数据库(一)-- 数据库介绍、MySQL安装、基础SQL语句
一.数据库介绍 1.什么是数据库 数据库即存储数据的仓库 2.为什么要用数据库 (1)用文件存储是和硬盘打交道,是IO操作,所以有效率问题 (2)管理不方便 (3)一个程序不太可能仅运行在同一台电脑上 ...
- Eslint 允许使用双等号
资料 网址 ESlint: Expected !== and instead saw != https://stackoverflow.com/questions/48375316/eslint-ex ...