Java 拾遗二

1. HashMap 和 HashTable 的区别

HashMap 线程不安全 允许有 Null 的键值 没有同步锁效率高 有 containsValue 和 contaninsKey 方法
HashTable 线程安全 不允许有 Null 的键值 有同步锁需要排队效率低 有 contains 方法

HashMap 是 HashTable 的一个轻量级的实现;
HashMap 是 Java 1.2 引入的 Map interface 的一个实现;
HashTable 继承自 Dictionary;

2. HashMap 和 ConcurrentHashMap 的区别

HashMap 是线程不安全的,ConcurrentHashMap 是线程安全的;
ConcurrentHashMap 具体是怎么实现线程安全的呢,肯定不可能是每个方法加synchronized,那样就变成了HashTable。
ConcurrentHashMap 引入了一个“分段锁”的概念,具体可以理解为把一个大的Map拆分成N个小的HashTable,根据key.hashCode()来决定把key放到哪个HashTable中。
ConcurrentHashMap 将数据分为多个segment,默认16个(concurrency level),然后每次操作对一个segment加锁,避免多线程锁的几率,提高并发效率。

final float loadFactor; //加载因子
载因子是表示Hash表中元素的填满的程度.若加载因子越大填满的元素越多空间利用率高了,但冲突的机会加大了。
反之,加载因子越小填满的元素越少冲突的机会减小了,但空间浪费多了。
冲突的机会越大,则查找的成本越高。反之,查找的成本越小查找时间就越小。
因此,必须在 "冲突的机会"与"空间利用率"之间寻找一种平衡与折衷.,这种平衡与折衷本质上是数据结构中有名的"时-空"矛盾的平衡与折衷。

HashMap 默认初始容量为16,默认加载因子为0.75。
从代码中看是确保容量为2的n次幂,使capacity为大于initialCapacity的最小的2的n次幂。

https://www.cnblogs.com/remember-forget/p/6021644.html

3. TreeMap、HashMap、LindedHashMap 的区别

共同点:
TreeMap、HashMap、LindedHashMap 都属于Map;
Map 主要用于存储键(key)值(value)对,根据键得到值,因此键不允许键重复,但允许值重复。

不同点:

  1. HashMap 里面存入的键值对在取出的时候是随机的,也是我们最常用的一个Map.它根据键的 HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。
    在 Map 中插入、删除和定位元素,HashMap 是最好的选择。
  2. TreeMap 取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap 会更好。
  3. LinkedHashMap 是 HashMap 的一个子类,如果需要输出的顺序和输入的相同,那么用 LinkedHashMap 可以实现。

4. Collection 包结构,与 Collections 的区别

Collection 是集合类的顶级接口;实现了接口类主要有 Set、List、LinkedList、ArrayList、Vector 等;
Collections 是针对集合类的一个帮助类,提供操作集合的工具方法;服务于 Java 的 Collection 框架;常用方法有 搜索、排序等;

5. try catch finally,try里有return,finally还执行么?

任何执行 try 或者 catch 中的 return 语句之前,如果finally存在都会先执行finally语句;
如果 finally 中有 return 语句那么程序就 return 了,所以finally中的return是一定会被return的,编译器把finally中的return实现为一个warning。

在try语句中,在执行return语句时,要返回的结果已经准备好了,就在此时,程序转到finally执行了。
在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,执行完finally之后,在从中取出返回结果,
因此,即使finally中对变量x进行了改变,但是不会影响返回结果,它应该使用栈保存返回值。

6. Excption 与 Error 包结构。OOM 你遇到过哪些情况,SOF 你遇到过哪些情况。

  • Throwable

Throwable是 Java 语言中所有错误或异常的超类。
Throwable 包含两个子类: Error 和 Exception 。它们通常用于指示发生了异常情况。
Throwable 包含了其线程创建时线程执行堆栈的快照,它提供了 printStackTrace() 等接口用于获取堆栈跟踪数据等信息。
Java将可抛出(Throwable)的结构分为三种类型: 被检查的异常(Checked Exception),运行时异常(RuntimeException)和错误(Error)。

  • Exception

Exception及其子类是 Throwable 的一种形式,它指出了合理的应用程序想要捕获的条件。

  • RuntimeException

RuntimeException是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。
编译器不会检查RuntimeException异常。 例如,除数为零时,抛出ArithmeticException异常。
RuntimeException是ArithmeticException的超类。当代码发生除数为零的情况时,倘若既"没有通过throws声明抛出ArithmeticException异常",也"没有通过try...catch...处理该异常",也能通过编译。这就是我们所说的"编译器不会检查RuntimeException异常"!
如果代码会产生RuntimeException异常,则需要通过修改代码进行避免。 例如,若会发生除数为零的情况,则需要通过代码避免该情况的发生!

  • Error

和Exception一样, Error也是Throwable的子类。 它用于指示合理的应用程序不应该试图捕获的严重问题,大多数这样的错误都是异常条件。 和RuntimeException一样, 编译器也不会检查Error。

  • OOM(OutOfMemory)和 SOF(StackOverFlow)
  1. 产生堆溢出(无限 new 对象)
    堆是存放实例对象和数组的地方,当对象多过设置的堆大小,同时避免GC回收即可。最大内存块Xmx和最小内存块Xms一样,堆就不可扩展了。将new出的对象放到List中可防止GC回收。
  2. 产生虚拟机栈或本地方法栈 StackOverFlow(递归调用)
    当请求的栈深度超过JVM允许最大深度即可,用Xss设置
  3. 产生虚拟机栈或方法栈 OutOfMemory(不断创建线程)
  4. 运行时常量池异常
    使用 String.interm() 填充常量池。intern 的作用是如果该常量不在常量池中,则添加到常量池,否则返回该常量引用。
    常量池是方法区一部分,运行时可限制方法区PermSize和最大方法区MaxPermSize大小
  5. 方法区溢出(通过CGLib将大量信息放到方法区)

7. Java 面向对象的三个特征与含义

  • 继承

是指可以让某个类型的对象获得另一个类型的对象的属性的方法。

  • 封装

是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

  • 多态

是指一个类实例的相同方法在不同情形有不同表现形式。

推荐阅读更多精彩内容