3 CollectionTest03.java
按照要求完成下列任务
(1)使用HashMap类实例化一个Map类型的对象m,键(String)和值(int)分别用于存储员工的姓名和工资,存入数据如下:
jack-650元;tom-1200元;smith-2900元;
(2)将jack的工资更改为2600元;
(3)为所有员工工资加薪100元;
(4)遍历所有员工;
(5)遍历所有工资。
🦁 参考代码及运行结果:
import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * @author 兴趣使然黄小黄 * @version 1.0 */ public class Collection03 { public static void main(String[] args) { Map map = new HashMap(); map.put("jack", 650); // int - Integer map.put("tom", 1200); map.put("smith", 2900); System.out.println("初始数据: " + map); // 更新jack工资 map.put("jack", 2600); System.out.println("jack工资更新: " + map); // 所有员工加薪100元 Set keySet = map.keySet(); for (Object key : keySet) { // 更新 map.put(key, (Integer)map.get(key) + 100); } System.out.println("所有员工加薪100元: " + map); // 遍历员工与工资 Set entrySet = map.entrySet(); Iterator iterator = entrySet.iterator(); while (iterator.hasNext()){ Map.Entry entry = (Map.Entry)iterator.next(); System.out.println(entry.getKey() + "-" + entry.getValue()); } } }
4 简答题
4.1 试分析 HashSet 与 TreeSet 分别如何实现去重的?
❓ 试分析 HashSet 与 TreeSet 分别如何实现去重的?
- HashSet的去重机制: hashCode() + equals(),底层先通过存入对象,进行运算得到一个 hash值,通过 hash值得到对应的索引,如果发现table索引所在位置,没有数据,则直接存放;如果有数据,则进行equals比较(由程序员决定),遍历该链表,如果遍历比较后都不相同,则加入,否则不加入。
- TreeSet的去重机制: 如果传入了一个 Comparator匿名对象,则使用实现的 compare去重,如果方法返回0,则认为是相同数据,则不添加。如果没有传入 Comparator匿名对象,则以添加的对象实现的 Compareable 接口的 compareTo 去重。
5 代码分析题
5.1 下面的代码是否会抛出异常,并从源码层面说明原因?
TreeSet treeSet = new TreeSet(); treeSet.add(new Person());
答: 会。因为 TreeSet() 构造器没有传入 Comparator接口的匿名内部类,所以在底层会把 Person 对象 转成 Comparable 类型,但是,Person并没有实现该接口,所以会报异常:ClassCastException。
5.2 Person类按照id和name重写了hashCode和equals方法,问下面代码输出什么?(容易踩坑)
import java.util.HashSet; import java.util.Objects; /** * @author 兴趣使然黄小黄 * @version 1.0 */ public class MyTest { 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"; set.remove(p1); System.out.println(set); set.add(new Person(1001, "CC")); System.out.println(set); set.add(new Person(1001, "AA")); System.out.println(set); } } class Person{ public int id; public String name; public Person(int id, String name) { this.id = id; this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Person)) return false; Person person = (Person) o; return id == person.id && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(id, name); } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
🦁 注意陷阱!
在添加第一个 Person{1001, “AA”}时,hash值已经确定,而当修改AA为CC时,并不会更改hash值,而后,通过remove删除时,找不到原来的AA位置,所以导致删除失败!
在添加CC时,重新计算了hash值,和AA修改CC的索引并不相同,因此可以成功加入;
在最后添加AA时,计算出索引位置为第一个 Person的位置,但是其内容已经为CC,因此,能够以链表的形式接在其后面,也能添加成功!