因为自己的原因,java基础没有打的很牢靠,面对校招补全一下基础,顺便做点笔记。
String StringBuffer StringBuilder
String类是不可变类(指向内存地址所存储的内容不变,但是“指向”可以变)
例如:
String a=“12345”;假设a指向的地址是a123,存储的内容是12345
a=“2345”; 这里代码没有问题,不可变指的是地址a123所存储的内容不变,这里改变的是a所指向的地址,假设地址a234存储的是2345,这里的a就指向了4234.
StringBuffer对象则代表一个字符序列可变的字符串。即在不指定变换指向地址的情况下,StringBuffer对象所指向的地址存储的值是可以变化的,一般使用append(),insert(),delete()方法更改字符串。这里函数的参数我没有给出,有兴趣自查。
StringBuilder类也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。
StringBuffer实现线程安全
StringBuffer类中的方法都添加了synchronized关键字,也就是给这个方法添加了一个锁,用来保证线程安全。
hashmap
在哈希表中进行添加,删除,查找等操作,性能十分之高,不考虑哈希冲突的情况下(后面会探讨下哈希冲突的情况),仅需一次定位即可完成,时间复杂度为O(1),接下来我们就来看看哈希表是如何实现达到惊艳的常数阶O(1)的。
数据结构的物理存储结构只有两种:顺序存储结构和链式存储结构,在数组中根据下标查找某个元素,一次定位就可以达到,哈希表利用了这种特性,哈希表的主干就是数组。比如我们要新增或查找某个元素,我们通过把当前元素的关键字 通过某个函数映射到数组中的某个位置,通过数组下标一次定位就可完成操作。
这个函数可以简单描述为:存储位置 = f(关键字) ,这个函数f一般称为哈希函数,这个函数的设计好坏会直接影响到哈希表的优劣。这个函数可以简单描述为:存储位置 = f(关键字) ,这个函数f一般称为哈希函数,这个函数的设计好坏会直接影响到哈希表的优劣。
哈希冲突
如果两个不同的元素,通过哈希函数得出的实际存储地址相同怎么办?也就是说,当我们对某个元素进行哈希运算,得到一个存储地址,然后要进行插入的时候,发现已经被其他元素占用了,其实这就是所谓的哈希冲突,也叫哈希碰撞。前面我们提到过,哈希函数的设计至关重要,好的哈希函数会尽可能地保证 计算简单和散列地址分布均匀,但是,我们需要清楚的是,数组是一块连续的固定长度的内存空间,再好的哈希函数也不能保证得到的存储地址绝对不发生冲突。那么哈希冲突如何解决呢?哈希冲突的解决方案有多种:开放定址法(发生冲突,继续寻找下一块未被占用的存储地址),再散列函数法,链地址法,而HashMap即是采用了链地址法,也就是数组+链表的方式。
HashMap的实现原理
HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元,每一个Entry包含一个key-value键值对。(其实所谓Map其实就是保存了两个对象之间的映射关系的一种集合)
hashmap的原理看了下感觉不是我能讲懂的,各位大佬详情移步https://blog.csdn.net/woshimaxiao1/article/details/83661464
链表
线性链表:对于链表的新增,删除等操作(在找到指定操作位置后),仅需处理结点间的引用即可,时间复杂度为O(1),而查找操作需要遍历链表逐一进行比对,复杂度为O(n)