基础高频面试总结

1.HashMap

数组是在内存中开辟一段连续的空间,因此,只要知道了数组首个元素的地址,在数组中寻址就会非常容易,其时间复杂度为O(1)。但是当要插入或删除数据时,时间复杂度就会变为O(n)。
链表是内存中一系列离散的空间,其插入和删除操作的内存复杂度为O(1),但是寻址操作的复杂度却是O(n)。那有没有一种方法可以结合两者的优点,即寻址,插入删除都快呢?这个方法就是HashMap。

HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。

Map map = new HashMap(); // HashMap遍历
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
  Map.Entry entry = (Map.Entry) iter.next();
  Object key = entry.getKey();
  Object val = entry.getValue();
}
put的主要步骤为一下几点:
1.先根据key计算出hash值,并用hash值计算出元素应在数组中的哪个位置。
2.判断这个位置上是否为空,若为空,直接调用addEntry方法将元素加入,并且返回null

3.若不为空,将这个位置上的元素统一向这个位置所连的链表后方推一格,然后将要加入的元素放在链表头部(类似一个栈)。返回以前的链表头部元素。

get方法实际是调用了getEntry方法。首先计算 key 的 hashCode,找到数组中对应位置的某一元素,然后通过 key 的 equals 方法在对应位置的链表中找到需要的元素。

疑问:其实还是不太明白为啥需要链表,难道添加元素的时候算出的hash值所在位置已经有元素了,然后还会将该元素放到这个位置,放在链表的头部吗?那这样的话数组上的某个元素可能会有好多个元素啊。。下面2中红色位置是说明了这个原因吗????

2.equals

Object类中的equals方法和“==”是一样的,没有区别,即俩个对象的比较是比较他们的栈内存中存储的内存地址。而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,他们比较的是值是不是相等。所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。

Java中的Collection有两类,一类是List,一类是Set。List内的元素是有序的,元素可以重复。Set元素无序,但元素不可重复。要想保证元素不重复,两个元素是否重复应该依据什么来判断呢?用Object.equals方法。但若每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说若集合中已有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。于是Java采用了哈希表的原理。当Set接收一个元素时根据该对象的内存地址算出hashCode,看它属于哪一个区间,再这个区间里调用equeals方法。【特别注意】这里需要注意的是:当俩个对象的hashCode值相同的时候,Hashset会将对象保存在同一个位置,但是他们equals返回false,所以实际上这个位置采用链式结构来保存多个对象。 


3.扑克牌算法

public void shuffle(int[] arr){
    int i = arr.length;
    int j = 0;int temp = 0;
    while(--i){
        Random r = mew Random();
        j = r.nextInt(54) + 1;
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

其实就是每次随机一个数,将随机的这个数字与最后一个元素进行交换,然后将整个数组减小,直到剩余数组为1就结束。
据说这是最好的洗牌算法,因为保证了每一个数出现在所有位置上的概率是相等的,降低了时间和空间复杂度。Fisher-Yates shuffle算法。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值