1.寻址次数链表要多一些。数组只需对基地址+元素大小*k就能找到第k个元素的地址 对其取地址就能获得该元素。链表要获得第k个元素,首先要在其第k-1个元素寻找到其next指针偏移,再将next指针作为地址获得值。多了一步寻址操作,当数据量大且其它操作较少时 这就有差距了
2.CPU缓存会把一片连续的内存空间读入,因为数组结构是连续的内存地址,所以数组全部或者部分元素被连续存在CPU缓存里面,平均读取每个元素的时间只要3个CPU时钟周期。 而链表的节点是分散在堆空间里面的,这时候CPU缓存帮不上忙,只能是去读取内存,平均读取时间需要100个CPU时钟周期。这样算下来,数组访问的速度比链表快33倍! (这里只是介绍概念,具体的数字因CPU而异)。
哈希(散列结构):
散列结构有什么好处?解决了什么问题?
优点:
哈希表使用hash function来对输入的数据分配index到哈希表对应的槽中。假设有一个哈希表的size是100,而我们输入的数据是从0~99,我们要把输入数据储存到哈希表中。理论上来说,该哈希表插入和查找操作的时间复杂度都是O(1)。
缺点:
很简洁的一个乘加迭代运算,在不少的hash算法中,使用的是异或+加法进行迭代,速度和前者差不多。
为什么string要实现序列化,要定义private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
这个类的作用是创建具有指定类型的序列化对象。
这个字段?
目前怀疑是把char value[]这个字段给序列化了,打印的时候是对char的反序列化过程
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
/**
* Class String is special cased within the Serialization Stream Protocol.
*
* A String instance is written into an ObjectOutputStream according to
* Object Serialization Specification, Section 6.2, "Stream Elements"
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
/**
* Initializes a newly created {@code String} object so that it represents
* an empty character sequence. Note that use of this constructor is
* unnecessary since Strings are immutable.
*/
public String() {
this.value = "".value;
}
String的equals方法:比较string内char数组的值是否不等
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
/**
* 这个是什么意思呢》返回一个string对象本身?
为什么这样返回就不打印哈希值而是直接打印字符?
*
* @return the string itself.
*/
public String toString() {
return this;
}
打印对象的引用时,会默认调用Object类的toString()方法,返回的是一个字符串表示,该字符串的形式为类名+@+十六进制的哈希值;为什么String打印的不是这样一个地址值呢?因为String类继承自Object类,重写了从Object类拿到的toString()方法,返回的是该该对象本身,即字符串。
API中Object类的toString()方法:
public String toString()
返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。
Object 类的 toString 方法返回一个字符串:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public native int hashCode();
String的hashcode为什么是质数:
首先来说假如关键字是随机分布的,那么无所谓一定要模质数。但在实际中往往关键字有某种规律,例如大量的等差数列,那么公差和模数不互质的时候发生碰撞的概率会变大,而用质数就可以很大程度上回避这个问题。
质数并不是唯一的准则,具体可以参考以下网站。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}