1. 向下转型问题
HashMap m = new HashMap();
m.put("jack", 650);
Set keyset = m.keySet();
for(Object key : keyset) {
m.put(key, (Integer)m.get(key) + 100);
//m.get(key)返回的类型是Object,这里需要Integer型,要向下转型
}
2. 分析HashSet和TreeSet分别如何实现去重
2.1 HashSe: hashCode() + equals(),底层先通过存入对象生成hash值,通过hash值得到在table表的索引,如果该索引位置没有元素则直接加入,否则equals比较遍历该索引及后面的链接元素,没有相同的就加入,否则不加入。
2.2 TreeSet去重机制:如果传入一个Comparator匿名对象,就是用实现的compare去重,如果方法返回0,就认为是相同的元素,就不添加,如果没有传入一个Comparator匿名对象,则以你添加的对象实现的Compareable接口的compareTo去重
3. 运行以下代码会不会抛出异常
TreeSet treeset = new TreeSet();
treeset.add(new Person());
class Person{}
会抛出ClassCastException异常。
因为TreeSet底层比较的类必须是实现了Comparable接口的类,而Person类没有实现此接口
可改为如下代码:
class Person implements Comparable{
@Override
public int compareTo(Object o) {
return 0;
}
}
但这样只能在treeset中加入一个Person对象,因为Comparable返回0
4. HashSet修改存入对象后的坑
public class Homework06 {
public static void main(String[] args) {
HashSet set = new HashSet();
Person p1 = new Person(1001,"AA");
Person p2 = new Person(1002, "BB");
set.add(p1);
set.add(p2);
p1.name = "CC";
//p1的属性被修改,但p1放入set的位置是根据修改前的属性确定的
set.remove(p1);
//此时被修改的p1定位不到原本的位置因为删除不了,Q:有没有误删其他元素的可能?
System.out.println(set);
//仍然存有两个对象
set.add(new Person(1001, "CC"));
//根据1001和CC获得hash值并得到索引位置,和之前的1001和AA位置不同,成功加入
System.out.println(set);
//有三个对象
set.add(new Person(1001, "AA"));
//根据1001和AA得到哈希值和索引位置,但之前存入的p1的name已经更改,会识别为两个不同的对象,挂在p1后
System.out.println(set);
//四个对象
}
}
class Person{
int number;
String name;
Person(int number, String name) {
this.number = number;
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 number == person.number &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(number, name);
}
@Override
public String toString() {
return "Person{" +
"number=" + number +
", name='" + name + '\'' +
'}';
}
}