有两三个月没看Java基础,遇到面试题就又只有零碎的印象了。
1、Java中 == 和 equals 的区别?
一开始只清楚 == 用于处理基本数据类型(Byte、Short、Char、Int、Long、Float、Double、Boolean),而String类等引用数据类型使用equals。
实际上, == 判断左右内容是否指向同一个内存空间(因为值类型储存在栈中,引用类型仅有地址储存在栈中,内容储存在堆中)。
equals则是判断左右引用类型的内容是否相等,即在堆中的内容是否相同。
2、List,Set和Map之间的区别?
这个我对List留下的印象是数据结构中的顺序表和链表,没有考虑到Vector。
ArrayList就是用数组实现的List接口,LinkedList是用双向链表实现的。其中区别还是在于插入移除数据,数组实现显然需要开辟连续的储存空间,好处在于知道下标就可以O(1)查找,但是中间插入数据需要将之后的数全部后移一格。链表使用Node节点包括了前后节点的地址,就不需要后移了,直接修改前节点和后节点的地址就可以了,但是不能用下标意味着寻找第n个数需要从头遍历。Vector通过加入同步锁,保证了线程安全,当然额外的操作会降低效率。容量不足时自动翻倍。具体实现和ArrayList类似,是数组。
Set在Leetcode里用的多,自己只用过HashSet所以认识不够清楚。(我以前觉得HashSet基本就是K和V相等的HashMap)其实Set是容纳不重复的集合,实现也可以不用HashCode的方式的,比如TreeSet就是红黑树结构,而且TreeSet是有序的(这里的有序与Set不冲突,TreeSet是可排序输出)(LinkedHashSet是有序的)。
接下来有一个问题,既然HashSet用了散列的方式,是根据Key的哈希操作来确定位置的,那么以不同的顺序输入同一组数据,其输出是否相同呢?
public class Test1 { public static void main(String[] args) { Set<Integer> set1 = new HashSet<Integer>(); Set<Integer> set2 = new HashSet<Integer>(); set1.add(1); set1.add(2); set1.add(3); set2.add(3); set2.add(2); set2.add(1); System.out.println(set1); System.out.println(set2); } }

public static void main(String[] args) { Set<Integer> set1 = new HashSet<Integer>(); Set<Integer> set2 = new HashSet<Integer>(); set1.add(1); set1.add(2); set1.add(3); set1.add(18); set2.add(1); set2.add(18); set2.add(2); set2.add(3); System.out.println(set1); System.out.println(set2); }

HashSet的add直接调用HashMap的put方法,且以e作为Key。HashMap的put调用hash方法,而hash方法使用.hashCode()和扰动函数,最后再用散列值对数组长度进行取模运算取得余数。 (这块涉及源码,网上找到了详细分析 https://www.cnblogs.com/ideal-20/p/11146733.html )
使用了散列就要考虑冲突。解决冲突有几种简单办法:线性探查法,平方探查法,和链地址法(拉链法)。其中链地址法不计算新的Hash值,直接把H(key)相同的key值连接成一条单链表,而HashMap使用的就是链地址法。既然使用了链地址法,那么一组数据在环境中存在哈希冲突的情况下,以不同的顺序输入,那么冲突所产生的链表中的顺序将会根据输入的顺序来排列,在输出时也会根据输入的顺序的不同而不同。
已知在数组初始长度小于16的情况下,2与18会产生冲突,调整2和18添加进HashSet的顺序,输出循序也因此而改变。