Java常见面试题总结
来源:互联网 发布:尸者的帝国知乎 编辑:程序博客网 时间:2024/06/06 10:03
1.Map是否能用自定义对象来做key,如果能,有什么要求?
答:只要能保证key的唯一性就可以做key,首先看一下HashMap和TreeMap在添加元素时是如何保证key的唯一性的?
HashMap
HashMap底层的数据结构,是数组加单链表.jdk源码:
/*通过对加进来的key的hashcode进行hash(hash函数,用来使元素均匀分布的)处理,然后找到对应的数组位置,如果该位置已经有元素了,那么就存储在该位置的链表的末位(越先在该位置的越靠前).*//*判断key是否相等的过程:先看hash(hashcode)的值是否相等,然后看==或equals是否相等.如果相等则用新的value替代旧的value,并将旧的value返回.*///hashMap的put方法.public V put(K key, V value) { return putVal(hash(key), key, value, false, true);}final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }//hashMap的containsKey方法.public boolean containsKey(Object key) { return getNode(hash(key), key) != null;}final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) { if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }
TreeMap
TreeMap的底层数据结构是二叉树.jdk源码:
/*排序时有两种方式,一种是通过自身的Comparator进行排序,另一种是通过实现了Comparable接口的key进行排序,优先使用第一种方式,当持有的Comparator(默认为null)为null时则采用第二种方式.*//*如果相等则用新的value替代旧的value,并将旧的value返回.*///treeMap的put方法.public V put(K key, V value) { Entry<K,V> t = root; if (t == null) { compare(key, key); // type (and possibly null) check root = new Entry<>(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(); @SuppressWarnings("unchecked") 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<>(key, value, parent); if (cmp < 0) parent.left = e; else parent.right = e; fixAfterInsertion(e); size++; modCount++; return null; }//treeMap的containsKey方法. public boolean containsKey(Object key) { return getEntry(key) != null; } final Entry<K,V> getEntry(Object key) { // Offload comparator-based version for sake of performance if (comparator != null) return getEntryUsingComparator(key); if (key == null) throw new NullPointerException(); @SuppressWarnings("unchecked") Comparable<? super K> k = (Comparable<? super K>) key; Entry<K,V> p = root; while (p != null) { int cmp = k.compareTo(p.key); if (cmp < 0) p = p.left; else if (cmp > 0) p = p.right; else return p; } return null; }
2.String类的常见面试题
String s1 = "a";String s3 = "ab";String s4 = s1 + "b";String s5 = "a"+"b";(1)System.out.println(s3 == s4); //false(2)System.out.println(s3 == s5); //true(3)System.out.println(s3.intern() == s5); //true(4)System.out.println(s3.intern() == s5.intern()); //true
Java的String类型的字符串都是不可变的,String类使用final修饰的.所以只要有一个字符串被确定的用双引号声明了以后,就会被放到字符串常量池里面.常量池里面的相同的字符串常量无论是用”==”比较还是”equals方法”比较都是返回true.
解释(1) :所以s3 = “ab”,此时字符串”ab”是会被放到常量池里面,但是s4 = s1 + “b”,中的s4是由变量s1和”b”共同组成的,所以s4其实是一个变量,所以不会被储存在常量池里面,而是储存在堆内存中.
解释(2) : s3和s5都能被确定下来,所以被储存在常量池里面.
解释(3)或(4) : 字符串调用intern()的执行过程是,判断字符串常量池里面是否含有当前字符串,如果含有则直接返回,如果不含有,则把当前字符串放到字符串常量池里面,并返回.(intern()方法之后”==”的结果与字符串调用equals方法的结果一样)
阅读全文
0 0
- java常见面试题总结
- java常见面试题总结
- java常见面试题总结
- Java常见面试题总结
- Java常见面试题总结
- Java多线程面试题总结(常见多线程面试题)
- 总结Java常见面试题和答案
- 总结Java常见面试题和答案
- 常见的Java面试题总结
- 常见面试题 总结
- 常见面试题总结
- Java常见面试题
- java常见面试题
- java常见面试题
- java常见面试题
- java常见面试题
- java常见面试题
- Java常见面试题
- 安全审计
- java调用短信api发送短信进行注册
- js jquery js的DOM与Jquery相互转换,js控制select的方法
- js jquery js的DOM与Jquery相互转换,js控制select的方法
- Linux串口(serial、uart)驱动程序设计
- Java常见面试题总结
- QQ第三方登录实现
- [DP][倍增NTT]LOJ#6059. 2017 山东一轮集训 Day1. Sum
- javaScript之数组去重
- 第一天的博客
- jquery table 鼠标选中单元格效果
- 自定义GridView添加头视图和足视图
- HTML 速查列表
- vtk处理外部事件