前段时间我去某知名的医疗领域互联网公司面试架构师,殊不知某司在面试架构师级别人才时也需要做笔试题目
因毫无准备当时我一下子有些懵掉了。结果可想而知,本次面试情况不理想。在此整理一下将题目记录一下。
题目与结果
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笔试题汇总资料188个合集 100家大公司java笔试题汇总.doc 125条常见的java 面试笔试题大汇总.pdf 2011最新整理java经典代码.doc 25个经典的Spring面试问答.docx ...
java面试资料java面试题集java笔试题汇总资料,java面试资料java面试题集java笔试题汇总资料,java面试资料java面试题集java笔试题汇总资料,包括基础面试题、JavaWeb面试题、JAVA面试题集.txt、分布式相关面试题...
java面试笔试题库java软件设计java笔试题大集合及答案文档资料合集300MB“ 100家大公司java笔试题汇总.doc 125条常见的java 面试笔试题大汇总.pdf 2011最新整理java经典代码.doc 25个经典的Spring面试问答.docx 8张...
这份"java笔记java笔试题 java面试题"的资源无疑是准备Java程序员的笔试和面试时的重要参考资料。以下是一些关键的Java知识点,这些内容可能会在笔记或面试中出现: 1. **Java基础**:Java的基础语法包括数据类型...
Java 试题、Java 笔试题、Java 面试题 本资源摘要信息中,我们将对 Java 相关试题、笔试题和面试题进行总结和分析,涵盖了 XML 解析技术、Struts 框架、ArrayList 和 Vector 的区别、HashMap 和 Hashtable 的区别、...
以下是对标题和描述中涉及的一些常见Java面试题的详细解释: 1. **JDK 和 JRE 的区别** JDK(Java Development Kit)是用于开发和调试Java程序的完整工具集,包括JRE(Java Runtime Environment)、编译器(javac...
为了在Java面试中脱颖而出,了解和掌握常见的面试题及答案至关重要。以下是一些关键知识点的详细解析: 1. **super()与 this()的区别** `super()`用于调用父类的构造器,确保子类实例化时父类的初始化;`this()`则...
java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 ...