今天,接了一个电话面试,对于还是初学者的我来说,紧张了半天。
面试的问题分了层次,对于一类问题,由简到难。自己觉得回答不好的地方作了一下总结:
在谈到集合类的时候,举几个常用的集合类,想都没想,直接说了list,map。
然后对list和map分别举几个类型:
list方面:ArrayList,LinkedList。在谈到他们的区别时,愣住了。就说了LinkedList是按照顺序存储的,ArrayList则是随机的。
后来翻了一下书:两者的不同之处不仅在于执行某些类型的操作时的性能,而且LinkedList包含的操作也多于ArrayList。
ArrayList:擅长于随机访问元素,但是在List的中间插入和移除元素较慢。
LinkedList:通过较低的代价在List中间进行元素的插入和删除操作,提供了优化的顺序访问。但是在随机访问方面相对比较慢,特性集较ArrayList更大。
它们都是具有相同接口和外部行为的简单的序列,但是它们对某些操作所花费的代价却有天壤之别。在ArrayList中,随机访问元素是一个花费固定时间的操作;但是,对LinkedList来说,随机选取元素需要在列表中移动,这种代价是高昂的,访问越靠近表尾的元素,花费的时间越长。而另一方面,如果想在序列中间插入一个元素,LinkedList的开销却比ArrayList要小。
map方面:举了hashmap,treemap,linkedhashmap。
谈到hashmap的时候,我对它只有“它是最快获得元素的方式”这个概念。然后被问到了hashcode,怎么产生hashcode的。我知道它和equals都可以用来比较两个对象是否相等,而且都可以重写。一般equals相等的两个对象,hashcode也基本相等。hashcode相等的,equals可能相等,可能不相等。但是hashcode是怎么产生的还真不知道。
回头查了一下,原来,hashcode是一个本地方法。在Object类中的代码是:
public native int hashCode();
如果不对它进行重写,那么两个地址不同的对象,hashcode是不会相同的。但是我们往往要比较的是两个对象的内容,那么就要对hashcode进行重写。举个例子:
public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
这是String重写后的hashcode。那么就可以用它来比较两个String的内容是否相同了。
public class TestEqualAndHash { public static void main(String[] args) { String a = "abc"; String b = "abc"; System.out.println(a==b); System.out.println(a.hashCode()==b.hashCode()); User u1 = new User(); User u2 = new User(); System.out.println(u1==u2); System.out.println(u1.hashCode()==u2.hashCode()); } } class User{ } Output: true true false false
可以看出,String经过重写,a,b相等;但是User没有重写过equals和hashcode,所以不相等。