前段时间我去某知名的医疗领域互联网公司面试架构师,殊不知某司在面试架构师级别人才时也需要做笔试题目
因毫无准备当时我一下子有些懵掉了。结果可想而知,本次面试情况不理想。在此整理一下将题目记录一下。
题目与结果
public class Main implements Comparable<Main> { private int _id; private int _sort; public Main(int id, int sort) { this._id = id; this._sort = sort; } public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Main)) { return false; } Main o = (Main) obj; return this._id == o._id; } /** * <p> * Description: * </p> * * @param o * @return * @see java.lang.Comparable#compareTo(java.lang.Object) */ @Override public int compareTo(Main o) { if (!equals(o)) { return Integer.valueOf(o._sort).compareTo(this._sort); } return 0; } public String toString() { return this._id + ":" + this._sort; } public static void main(String[] args) { TreeSet<Main> set = new TreeSet<Main>(); set.add(new Main(1, 1)); set.add(new Main(2, 2)); set.add(new Main(1, 3)); set.add(new Main(2, 3)); set.add(new Main(1, 4)); Iterator<Main> it = set.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } }
要求根据上面的这段程序代码写出相应的输出结果,正确的结果如下:
2:2 1:1
考察点分析
后面我们再回到题目本身去思考,为什么面试官会出这样一条笔试题目呢?下面是我事后分析的结论
1、考察面试者对Object类的equals()方法的理解
2、考察面试者对Object类的toString()方法的理解
3、考察面试者对TreeSet类内部数据结构的理解
结果分析
接下来我们分析一下为什么是这样一个结果呢?首先我们还是从main方法开始分析
1、创建TreeSet后先添加一个Mai(1,1)实例。调试发现TreeSet内部是使用TreeMap存储
接下来我们再查看TreeMap类的put(K key, V value)方法的内部代码结构
public V put(K key, V value) { Entry<K,V> t = root; if (t == null) { // TBD: // 5045147: (coll) Adding null to an empty TreeSet should // throw NullPointerException // // compare(key, key); // type check root = new Entry<K,V>(key, value, null); size = 1; modCount++; return null; } int cmp; Entry<K,V> parent; // split comparator and comparable paths Comparator<? super K> cpr = comparator; if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } else { if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } Entry<K,V> e = new Entry<K,V>(key, value, parent); if (cmp < 0) parent.left = e; else parent.right = e; fixAfterInsertion(e); size++; modCount++; return null; }
通过调试得出执行set.add(new Main(1, 1));时由于root为空执行的应该是以下代码块
- Entry<K,V> t = root;
- if (t == null) {
- // TBD:
- // 5045147: (coll) Adding null to an empty TreeSet should
- // throw NullPointerException
- //
- // compare(key, key); // type check
- root = new Entry<K,V>(key, value, null);
- size = 1;
- modCount++;
- return null;
- }
2、接下来我们分析执行set.add(new Main(2, 2))代码行的过程,通过调试分析我们会发现由于这个时候比较器comparator还是为空。因此会进入TreeMap的public V put(K key, V value)方法内部的以下代码块
else { if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); }
通过上面这部分代码我们进一步分析cmp = k.compareTo(t.key);代码行的执行过程,从这里我们可以看出来k==new Main(2, 2),t.key==new Main(1, 1),因此代码会执行到public int compareTo(Main o)方法
public int compareTo(Main o) { if (!equals(o)) { return Integer.valueOf(o._sort).compareTo(this._sort); } return 0; }内部首先会执行重写Object类的public boolean equals(Object obj)方法
public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Main)) { return false; } Main o = (Main) obj; return this._id == o._id; }
从上面两段代码我们可以分析出来cmp = k.compareTo(t.key);比较的结果为-1,在此过程中do{}while()仅会执行一次,最终结果cmp<0, Mai(2,2)会作为Main(1,1)的左叶子节点,具体执行的过程如下
do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; } while (t != null); } Entry<K,V> e = new Entry<K,V>(key, value, parent); if (cmp < 0) parent.left = e;
TreeMap结构图
3、接下来我们分析执行set.add(new Main(1, 3))代码行的过程,因此TreeMap的比较器comparator没有设值,因此执行的代码块如下:
else { if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); }
在这里我们看一下k.compareTo(t.key);这里的k==new Main(1, 3),t.key==new Main(1, 1),因此执行完Main的public int compareTo(Main o)方法后cmp==0。因此new Main(1, 3)由于key重复直接丢弃掉,具体执行的代码块如下:
else return t.setValue(value);
TreeMap结构图
4、接下来我们分析执行set.add(new Main(2, 3))代码行的过程,通过调试分析关键代码行cmp = k.compareTo(t.key)中k==new Main(2, 3),t.key==new Main(1, 1)。通过do{}while()代码块new Main(2, 3)会跟TreeMap现有所有节点从根节点进行逐一比较,第一次比较结果为cmp<0,因此new Main(2, 3)接着跟TreeMap中的左子节点new Main(2, 2)进行比较,第二次比较结果为cmp==0。因此new Main(2, 3)由于key重复直接丢弃掉,具体执行过程如下:
else { if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); }
TreeMap结构图
5、最后我们分析执行set.add(new Main(1, 4))代码行的过程,通过调试分析关键代码行cmp = k.compareTo(t.key)中k==new Main(1, 4),t.key==new Main(1, 1)。因此第一次k.compareTo(t.key)的结果为cmp = 0,由于存在重复的key直接丢弃new Main(1, 4)。最终的TreeMap结构如下:
TreeMap结构图
最后我们把各个Main的添加顺序调整一下,大家可以猜猜输出的结果又会是怎样的呢?
public static void main(String[] args) { TreeSet<Main> set = new TreeSet<Main>(); set.add(new Main(2, 2)); set.add(new Main(1, 1)); set.add(new Main(1, 3)); set.add(new Main(2, 3)); set.add(new Main(1, 4)); Iterator<Main> it = set.iterator(); while (it.hasNext()) { System.out.println(it.next()); } }
相关推荐
1、java笔试题大集合 2、各个公司面试题 3、J2EE初学者面试题 4、J2EE面试题(打码查错题) 5、java_华为笔试题 6、java常见面试题 7、java程序员面试宝典 8、java面试题及答案 9、java面试题编程篇 10、Oracle面试...
JAVA笔试题,面试题JAVA笔试题,面试题JAVA笔试题,面试题JAVA笔试题,面试题JAVA笔试题,面试题
大唐电信JAVA笔试题面试题 27 西安电讯盈科java笔试题 27 华为Java笔试题: 28 Java多线程常见面试题 31 Java企业面试题整理集合(1) 34 Java企业面试题整理集合(2) 43 Java企业面试题整理集合(3) 55 Java企业面试题...
Java面试题以及答案整理
java面试资料java面试题集java笔试题汇总资料,java面试资料java面试题集java笔试题汇总资料,java面试资料java面试题集java笔试题汇总资料,包括基础面试题、JavaWeb面试题、JAVA面试题集.txt、分布式相关面试题...
java试题 java笔试题 java面试题java试题 java笔试题 java面试题
java笔试题面试题java笔试题面试题java笔试题面试题java笔试题面试题java笔试题面试题java笔试题面试题
java面试笔试题库java软件设计java笔试题大集合及答案文档资料合集300MB“ 100家大公司java笔试题汇总.doc 125条常见的java 面试笔试题大汇总.pdf 2011最新整理java经典代码.doc 25个经典的Spring面试问答.docx 8张...
java面试笔试资料java笔试题大集合及答案题库java笔试题汇总资料188个合集 100家大公司java笔试题汇总.doc 125条常见的java 面试笔试题大汇总.pdf 2011最新整理java经典代码.doc 25个经典的Spring面试问答.docx ...
JAVA面试题JAVA面试题JAVA面试题JAVA面试题JAVA面试题JAVA面试题
java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 ...
100家大公司java笔试题汇总.docx
java面试笔试资料Java经典项目集锦java笔试题大集合及答案题库java笔试题汇总资料个合集(188) 100家大公司java笔试题汇总.doc 125条常见的java 面试笔试题大汇总.pdf 2011最新整理java经典代码.doc 25个经典的Spring...
面试题包含了不同技术层面的面试问题,同时也能对一些没有面试开发经验的小白给予不可估量的包装, 让你的薪水绝对翻倍, 本人亲试有效.Java面试题84集、java面试专属及面试必问课程,所有的面试题有视屏讲解, 解答方案....
这套面试题主要目的是帮助那些还没有java软件开发实际工作经验,而正在努力寻找java软件开发工作的朋友在笔试时更好地赢得笔试和面试。由于这套面试题涉及的范围很泛,很广,很杂,至少需要一个月的时间才能消化和...
JAVA面试题和笔试题总汇(含答案)
这是面试中常出现的java面试题 ex:【考题题干】类的设计要求它的某个成员变量不能被外部类直接访问。应该使用下面的哪些修饰符 获得需要的访问控制。 A .public B .no modifier C .protected D .private 【试题...
java面试题汇总java笔试题大集合及答案题库java笔试题汇总资料超过100个合集