🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
1. TreeSet底层的数据结构?      TreeSet的构造器都是基于TreeMap实现的,TreeMap底层的数据结构是红黑树,所以TreeSet底层的数据结构也就是红黑树。其中TreeSet的键作为TreeMap的Key来存放,而值使用了TreeSet类中定义的一个静态常量对象:private static final Object PRESENT = new Object(); 来作为值。 > 备注:美团一面   2. static修饰的变量是线程安全的嘛?final呢?      static修饰的变量和线程安全无关,static更多影响的是变量的存储位置,及不同对象对该变量的访问及占用情况,总之并不是线程安全的。  ​    而对于final修饰的变量,其是不能禁止修改的,而线程安全问题更多讨论的时候多线程的情况下变量能否保持一致性的问题。在变量本身不能被修改的情况下讨论线程安全是没有意义的。 >备注:美团一面   3. System.out.println()是线程安全的嘛?      是线程安全的,在println中调用了newLine方法,该方法中有一块被synchronized修饰的同步代码块。 >备注:美团一面   4. String为什么设计为final?   String类被final所修饰,不可以被继承,同时用来保存字符数据的char[]数组也是被final修饰,其引用也是不可以改变的。同时其有一个hash属性,对应该字符串的hashcode,在创建的时候就被计算出来,常用来作为Key存储。   设置成final的好处就是在高并发的场景下,不可变资源是不允许写操作的,能够保证线程安全;同时String的不可变性时期能够支持字符串常量池的设计,缓存字符串,提高程序的运行效率。 > 备注:美团一面   4. hashCode和equals的区别?hashCode用来做什么的?hashCode冲突怎么解决?hashCode和equals什么时候重写?   hashCode和equals都是Object类中的定义的方法,其中hashCode是用来标识一个对象,equals用来比较两个对象是否相同。hashCode和equals一般在需要将自定义的对象放入集合容器的时候会进行重写。 > 备注:美团一面   5. 重载和重写?   重载运行同个方法名有多种不同的实现方式,重载的方法必须要求参数类型或者个数不同,不能根据返回值来进行重载。Java中的重写方法用@Override注解修饰,用于实现类实现接口的方法,或者用于子类扩充父类的功能,是多态的关键。 > 备注:美团一面   6. Java的异常分类?  可分为免检异常和必检异常  免检异常:即RuntimeException,在程序运行的过程中可能因为人为的原因出现,不需要强制处理,例如NullPointException。  必检异常:需要强制捕获或者throws,例如IOException。 :-: ![java异常继承体系](https://img-blog.csdnimg.cn/20200831124536263.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDE4NDk5MA==,size_16,color_FFFFFF,t_70#pic_center) > 备注:美团一面   7. Java容器的分类?  可分为Collection和Map,其中Collection存储的元素是单个对象的,Map存储的是键值对类型的数据。  Collection下面又可以具体分为List、Set和Queue。  Map常见的实现类有HashMap、HashTable、TreeMap等。   Queue中有可以进一步细分为阻塞队列,其中有ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue、DelayQueue。   另外一个独立的分支的话就是并发类的容器了,例如ConcurrentHashMap等。 > 备注:美团一面   8. 用Map存储有序,保证插入顺序的意思是?LinkedHashMap、TreeMap的具体应用场景? - 一般的Map本身的存储是没有顺序的,因为其底层用的哈希表的结构,而哈希表的存储是不会保证插入顺序的,但是可以使用LinkedHashMap来保证插入的顺序。 - LinkedHashMap底层中使用另外的一个链表结构来保存元素的插入顺序。LinkedHashMap可以用在需要顺序遍历和快速获取数据的场景中,其底层的链表结构可以保证元素的顺序遍历,而底层的哈希表的结构可以保证快速获取数据。另外一个重要场景就是用在FIFO和LRU中。 - TreeMap底层采用的是红黑树结构,红黑树是一棵有序的二叉树,可以用需要基于排序的统计功能。 > 备注:美团一面   9. HashMap的put过程? - 调用put方法会计算key的hash之后调用putVal方法。put方法相关的逻辑处理均在putVal中。 - 在第一次put的时候底层数组结构还没有创建,需要先调用resize()扩容方法进行创建。在没有指定初始容量的情况下创建大小为16的底层数组。 - 之后每次调用put方法时会先计算该key所在桶的位置,通过((n - 1)& hash)来计算,如果当前桶是空的,就直接封装成一个新节点后放入。 - 否则,判断key是否相同,==和equals都会进行判断。如果相同则直接替换值,如果不相同则在当前链表中寻找,知道最后一个位置key都不相同时进行插入。同时判断链表的长度是否等于8了,等于的话就会将链表转化成一个树结构。 > 备注:美团一面   10. ArrayList和LinkedList的区别? - ArrayList的底层存储结构是一个数组,而LinkedList的底层存储结构是带首尾指针的双向链表。 - 底层结构的不同也影响ArrayList和LinkedList在使用方式上的一些不同;链表结构支持随机访问,其时间复杂度为O(1),但是对于插入和删除操作的时间复杂度比较高是O(n)。适用于查找比较多的场景。 - LinkedList不支持随机访问,查找元素的时间复杂度是O(n)的,但是插入和删除的时间复杂度高,是O(1)的。 - ArrayList和LinkedList都不是线程安全的。 > 备注:美团一面、cvte一面   11. 有哪些线程安全的集合类,讲一下原理? - List的实现类有个Vector,是线程安全的,其所有的方法都使用synchronized修饰。 - Map的实现类有个HashTable,是线程安全的,其所有的方法也是使用synchronized修饰。 - 在Collections工具类中对非线程安全的集合类都进行了一次封装,其底层也是使用synchronized进行修饰的。 - JDK5.0之后新增了并发类容器。 备注:美团一面