容器篇以及底层实现原理

MAP接口

===============================================================================
一、HashMap
HashMap
HashMap数据结构是什么?
key-value是通过什么方式存储进去的?
解释hashcode、取余、去重等操作?
key取余之后它可能全部堆积在某几个key对应的链表上,这样造成该数据结构存储或者低效,怎么解决?
链表为什么要变成红黑树,什么时候链表变成红黑树,什么时候红黑树变回链表?
多个线程并发访问,可能造成容器更新或者操作出现问题,有什么办法解决吗?
HashMap中的方法都什么意思?底层实现?

===============================================================================
二、HashTable、LinkedHashMap 、Properties、TreeMap

HashTable、LinkedHashMap 、Properties、TreeMap

===============================================================================

Collection:
Set
一、HashSet
HashSet底层是基于HashSet实现的,它的内部只使用HashMap的键存储数据,所有元素的值都是用同一个Object对象;HashSet增删改查操作都是调用HashMap的,在他的源码中代码量特别少。

二、LinkedHashSet

三、TreeSet

===============================================================================
List
一、ArrayList
二、Vector
三、LinkedList

===============================================================================

1、说一说List、Map、Set的区别?

List和Set属于Collection集合体系,最顶层是Iterable接口,它定义迭代器,Collection接口是Iterable接口的子接口,它定义了集合操作基本的增删改查行为。List和Set都是Collection接口的子接口,List是线性,添加顺序和迭代顺序一致有序集合,它允许出现重复元素;而Set是添加顺序和迭代顺序不一致的有序集合,它不允许有重复元素。Map集合体系是键值对集合,它主要实现子类有HashMap、TreeMap和LindedHashMap;Set集合实现类底层是使用Map的实现类实现的,HashSet使用HashMap实现,TreeSet使用TreeMap实现。

2、Arraylist 与 LinkedList 区别?

底层实现:Arraylist使用数组动态扩容存储元素,LinkedList底层使用双向链表存储元素。
操作效率:ArrayList适合多读场景,LinkidList适合多写场景;因为数组查询快,增删慢,链表增删快,查询慢。
结构上:他俩都是线性集合存储结构,List的具体实现类。
线程安全性:他俩都是线程不安全的集合。

3、ArrayList 与 Vector 区别呢?为什么要用Arraylist取代Vector呢?

底层实现:底层都是使用Object数组,动态扩容存储元素。
线程安全性:ArrayList是线程不安全的,Vector是线程安全的,它使用synchronized对每个方法加锁保证安全。
使用选择上:Vector不会被使用,如果想要保证线程安全,使用CopyonWriteArrayList代替它。

4、ArrayList 实现了 RandomAccess 接口, 而 LinkedList 没有实现。为什么呢?

这个接口中没有需要实现的方法,它只是起到标识的作用;标识这个接口实现类可以随机访问。

5、HashMap 和 Hashtable 的区别
底层实现:在JDK8中,HashMap底层使用数组和链表或红黑树实现,使用拉链法解决hash冲突,当拉链长度到达 8时,会被转化成红黑树;HashTable底层使用数组和链表实现,同样使用拉链法解决hash冲突。
初始大小:HashMap初始大小是16,HashTable初始大小是11。
线程安全:HashMap是线程不安全的,HashTable是线程安全的。但是HashTable实现线程安全的方式是在每个 方法上使用synchronized方法。由于所有线程竞争同一把锁,所以效率低下,现在基本不会是用它, 而是使用ConcurrentHashMap代替它。
对null值的支持:HashMap允许空键,而HashTable不允许使用空键。

6、HashMap 和 HashSet区别
HashSet底层是基于HashSet实现的,它的内部只使用HashMap的键存储数据,所有元素的值都是用同一个Object对象;HashSet增删改查操作都是调用HashMap的,在他的源码中代码量特别少。

7、HashMap 的长度为什么是2的幂次方
HashMap默认长度为16,也就是2的2次幂,hash % length == hash & (length - 1),由于用与运算代替模加快计算效率。

8、ConcurrentHashMap 和 Hashtable 的区别
底层实现:都使用数组加链表或红黑树实现。使用拉链法或红黑树解决哈希冲突,当链表长度到达8,会转换成红 黑是。

线程安全性:HashMap是线程不安全的,ConcurrentHashMap是线程安全的。jdk8之前使用的分段锁,对整个 桶数组进行分段加锁每一把锁只锁一段数据,多线程环境下,访问不同的段就不会发生竞争而等待。 jdk8中对每个桶数组也就是每个冲突链或红黑树使用锁,每个桶数组使用一个锁,这个更细粒度降低 多线程环境的冲突概率,提高并发访问效率。

9、ConcurrentHashMap线程安全的具体实现方式/底层具体实现

10、ConcurrentHashMap 工作原理?如何统计元素个数?

11、如何选用集合?

主要根据集合的特点来选用,比如我们需要根据键值获取到元素值时就选用Map接口下的集合,需要排序时选择TreeMap,不需要排序时就选择HashMap,需要保证线程安全就选用ConcurrentHashMap.当我们只需要存放元素值时,就选择实现Collection接口的集合,需要保证元素唯一时选择实现Set接口的集合比如TreeSet或HashSet,不需要就选择实现List接口的比如ArrayList或LinkedList,然后再根据实现这些接口的集合的特点来选用。

12、collection和collections区别
13、什么是迭代器?
14、comparable 和 Comparator的区别
15、说一说 ==、equals()、hashcode()
= = 与 equals(重要)
= = : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型= =比较的是内存地址)。

equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

情况 1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
情况 2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。
举个例子:

public class test1 {
public static void main(String[] args) {
String a = new String(“ab”); // a 为一个引用
String b = new String(“ab”); // b为另一个引用,对象的内容一样
String aa = “ab”; // 放在常量池中
String bb = “ab”; // 从常量池中查找
if (aa = = bb) // true
System.out.println(“aabb");
if (a = = b) // false,非同一对象
System.out.println("a
b”);
if (a.equals(b)) // true
System.out.println(“aEQb”);
if (42 = = 42.0) { // true
System.out.println(“true”);
}
}
}
说明:

String 中的 equals 方法是被重写过的,因为 object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值。
当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。
27. hashCode 与 equals (重要)
面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 方法?”

hashCode()介绍
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在 JDK 的 Object.java 中,这就意味着 Java 中的任何类都包含有 hashCode() 函数。

散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)

为什么要有 hashCode
我们先以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode: 当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与该位置其他已经加入的对象的 hashcode 值作比较,如果没有相符的 hashcode,HashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的 Java 启蒙书《Head first java》第二版)。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。

通过我们可以看出:hashCode() 的作用就是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()在散列表中才有用,在其它情况下没用。在散列表中 hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。

hashCode()与 equals()的相关规定
如果两个对象相等,则 hashcode 一定也是相同的
两个对象相等,对两个对象分别调用 equals 方法都返回 true
两个对象有相同的 hashcode 值,它们也不一定是相等的
因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值