一、前言
本篇文章没有什么主题,就是一些零散点的总结。
周末没事看了几道蚂蚁金服的面试题,其中有好几道都是特别简单的,基础性的题目,就是我们平时用到的,但是发现要是完全说出来还是有一些不清楚的地方,所以小小的总结一下。
二、hashCode()方法理解
提到hashCode()必然会涉及equals()方法,二者是紧密相连的,其实面试中被问到这方面往往是考察集合存储对象判断相等的问题。
比如有如下Person类:
public class Person {
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
}
很简单吧,我这里只重写了equals方法,如果我们以Person类对象作为key存储在HashMap中,如下:
HashMap map = new HashMap();
map.put(new Person(45,"lisi"),"123");
System.out.println(map.get(new Person(45,"lisi")));
试想一下能正常取出"lisi"值吗?对HashMap源码看过的同学肯定知道取不出来,打印如下:
null
HashMap在取数据的时候会检查对应的key是否已经存储过,这个比较简单来说就是比较key的hashcode()值以及equals()是否相等的比较,只有二者均相同才会认为已经存储过,对于上述Person类我们只重写了equals方法,对于hashcode()方法默认调用的是Object类中的hashcode()方法:
public int hashCode() {
return identityHashCode(this);
}
不同对象会生成不同的hash值,所以严格来说hashcode()与equals()方法我们最好同时重写,否则与集合类结合使用的时候会产生问题,改造Person类添加如下hashcode()方法:
@Override
public int hashCode() {
return Objects.hash(age, name);//根据类中属性生成对应hash值
}
这样就可以正常获取对应值了。
HashMap中比较元素是否相同是根据Key的hashcode值以及equals来判断是否相同的。
三、Set集合常用类相关问题
Set集合常用与存储不重复的数据,也就是集合中数据都不相等,但是不同具体实现类判断是否相等是不一样,这也是面试中会问到的问题,比如TreeSet是怎么判断元素是否相同的?HashSet是怎么判断的?
其实稍微看一下源码就明白了,Set具体实现类都是依靠对应map来实现的:
- HashSet底层依靠HashMap来实现
- TreeSet底层依靠TreeMap来实现
- LinkedHashSet底层依靠LinkedHashMap来实现
HashSet
看一下HashSet源码吧:
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
static final long serialVersionUID = -5024744406713321676L;
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map =