1. HashMap和Hashtable的区别java
注:Fast-fail
机制:在使用迭代器的过程当中有其它线程修改了集合对象结构或元素数量,都将抛出ConcurrentModificationException,可是抛出这个异常是不保证的,咱们不能编写依赖于此异常的程序。c++
2. java的线程安全git
Vector、Stack、HashTable、ConcurrentHashMap、Properties程序员
3. java集合框架(经常使用)github
Collection - List - ArrayList
Collection - List - LinkedList
Collection - List - Vector
Collection - Queue - PriorityQueue
Collection - List - Vector - Stack
Collection - Set - HashSet
Collection - Set - TreeSet
Collection - Set - LinkedHashSet
Map - HashMap
Map - TreeMap
Map - HashTable
Map - LinkedHashMap
Map - ConcurrentHashMap复制代码
3.1 List集合和Set集合面试
List中元素存取是有序的、可重复的;Set集合中元素是无序的,不可重复的。正则表达式
CopyOnWriteArrayList:COW的策略,即写时复制的策略。适用于读多写少的并发场景算法
Set集合元素存取无序,且元素不可重复。sql
HashSet不保证迭代顺序,线程不安全;LinkedHashSet是Set接口的哈希表和连接列表的实现,保证迭代顺序,线程不安全。数据库
TreeSet:能够对Set集合中的元素排序,元素以二叉树形式存放,线程不安全。
3.2 ArrayList、LinkedList、Vector的区别
首先它们均是List接口的实现。
ArrayList、LinkedList的区别
1.随机存取:ArrayList是基于可变大小的数组实现,LinkedList是连接列表的实现。这也就决定了对于随机访问的get和set的操做,ArrayList要优于LinkedList,由于LinkedList要移动指针。
2.插入和删除:LinkedList要好一些,由于ArrayList要移动数据,更新索引。
3.内存消耗:LinkedList须要更多的内存,由于须要维护指向后继结点的指针。
Vector从JDK 1.0起就存在,在1.2时改成实现List接口,功能与ArrayList相似,可是Vector具有线程安全。
3.3 Map集合
Hashtable:基于Dictionary类,线程安全,速度快。底层是哈希表数据结构。是同步的。不容许null做为键,null做为值。
Properties:Hashtable的子类。用于配置文件的定义和操做,使用频率很是高,同时键和值都是字符串。
HashMap:线程不安全,底层是数组加链表实现的哈希表。容许null做为键,null做为值。HashMap去掉了contains方法。注意:HashMap不保证元素的迭代顺序。若是须要元素存取有序,请使用LinkedHashMap
TreeMap:能够用来对Map集合中的键进行排序。
ConcurrentHashMap:是JUC包下的一个并发集合。
3.4 为何使用ConcurrentHashMap而不是HashMap或Hashtable?
HashMap的缺点:主要是多线程同时put时,若是同时触发了rehash操做,会致使HashMap中的链表中出现循环节点,进而使得后面get的时候,会死循环,CPU达到100%,因此在并发状况下不能使用HashMap。让HashMap同步:Map m = Collections.synchronizeMap(hashMap);而Hashtable虽然是同步的,使用synchronized来保证线程安全,但在线程竞争激烈的状况下HashTable的效率很是低下。由于当一个线程访问HashTable的同步方法时,其余线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态。如线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,而且也不能使用get方法来获取元素,因此竞争越激烈效率越低。
ConcurrentHashMap的原理:
Hashtable容器在竞争激烈的并发环境下表现出效率低下的缘由在于全部访问Hashtable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不一样数据段的数据时,线程间就不会存在锁竞争,从而能够有效的提升并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分红一段一段的存储,而后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其余段的数据也能被其余线程访问。
ConcurrentHashMap的结构:
ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入互斥锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap相似,是一种数组和链表结构, 一个Segment里包含一个HashEntry数组,每一个HashEntry是一个链表结构的元素,当对某个HashEntry数组的数据进行修改时,必须首先得到它对应的Segment锁。
ConcurrentHashMap的构造、get、put操做:
构造函数:传入参数分别为 一、初始容量,默认16 二、装载因子 装载因子用于rehash的断定,就是当ConcurrentHashMap中的元素大于装载因子*最大容量时进行扩容,默认0.75 三、并发级别 这个值用来肯定Segment的个数,Segment的个数是大于等于concurrencyLevel的第一个2的n次方的数。好比,若是concurrencyLevel为12,13,14,15,16这些数,则Segment的数目为16(2的4次方)。默认值为static final int DEFAULTCONCURRENCYLEVEL = 16;。理想状况下ConcurrentHashMap的真正的并发访问量可以达到concurrencyLevel,由于有concurrencyLevel个Segment,假若有concurrencyLevel个线程须要访问Map,而且须要访问的数据都刚好分别落在不一样的Segment中,则这些线程可以无竞争地自由访问(由于他们不须要竞争同一把锁),达到同时访问的效果。这也是为何这个参数起名为“并发级别”的缘由。默认16.
初始化的一些动做:
初始化segments数组(根据并发级别获得数组大小ssize),默认16
初始化segmentShift和segmentMask(这两个全局变量在定位segment时的哈希算法里须要使用),默认状况下segmentShift为28,segmentMask为15
初始化每一个Segment,这一步会肯定Segment里HashEntry数组的长度.
put操做:
一、判断value是否为null,若是为null,直接抛出异常。
二、key经过一次hash运算获得一个hash值。将获得hash值向右按位移动segmentShift位,而后再与segmentMask作&运算获得segment的索引j。即segmentFor方法
三、使用Unsafe的方式从Segment数组中获取该索引对应的Segment对象。向这个Segment对象中put值,这个put操做也基本是同样的步骤(经过&运算获取HashEntry的索引,而后set)。
get操做:
一、和put操做同样,先经过key进行hash肯定应该去哪一个Segment中取数据。
二、使用Unsafe获取对应的Segment,而后再进行一次&运算获得HashEntry链表的位置,而后从链表头开始遍历整个链表(由于Hash可能会有碰撞,因此用一个链表保存),若是找到对应的key,则返回对应的value值,若是链表遍历完都没有找到对应的key,则说明Map中不包含该key,返回null。
定位Segment的hash算法:(hash >>> segmentShift) & segmentMask
定位HashEntry所使用的hash算法:int index = hash & (tab.length - 1);
注:
1.tab为HashEntry数组
2.ConcurrentHashMap既不容许key为null 也不容许value为null
3.5 Collection 和 Collections的区别
Collection是集合类的上级接口,子接口主要有Set 和List、QueueCollections是针对集合类的一个辅助类,提供了操做集合的工具方法:一系列静态方法实现对各类集合的搜索、排序、线程安全化等操做。
3.6 Map、Set、List、Queue、Stack的特色与用法
Set集合相似于一个罐子,"丢进"Set集合里的多个对象之间没有明显的顺序。 List集合表明元素有序、可重复的集合,集合中每一个元素都有其对应的顺序索引。 Stack是Vector提供的一个子类,用于模拟"栈"这种数据结构(LIFO后进先出) Queue用于模拟"队列"这种数据结构(先进先出 FIFO)。 Map用于保存具备"映射关系"的数据,所以Map集合里保存着两组值。
3.7 HashMap的工做原理
HashMap维护了一个Entry数组,Entry内部类有key,value,hash和next四个字段,其中next也是一个Entry类型。能够将Entry数组理解为一个个的散列桶。每个桶其实是一个单链表。当执行put操做时,会根据key的hashcode定位到相应的桶。遍历单链表检查该key是否已经存在,若是存在,覆盖该value,反之,新建一个新的Entry,并放在单链表的头部。当经过传递key调用get方法时,它再次使用key.hashCode()来找到相应的散列桶,而后使用key.equals()方法找出单链表中正确的Entry,而后返回它的值。
3.8 Map的实现类的介绍
HashMap基于散列表来的实现,即便用hashCode()进行快速查询元素的位置,显著提升性能。插入和查询“键值对”的开销是固定的。能够经过设置容量和装载因子,以调整容器的性能。
LinkedHashMap, 相似于HashMap,可是迭代遍历它时,保证迭代的顺序是其插入的次序,由于它使用链表维护内部次序。此外能够在构造器中设定LinkedHashMap,使之采用LRU算法。使没有被访问过的元素或较少访问的元素出如今前面,访问过的或访问多的出如今后面。这对于须要按期清理元素以节省空间的程序员来讲,此功能使得程序员很容易得以实现。
TreeMap, 是基于红黑树的实现。同时TreeMap实现了SortedMap接口,该接口能够确保键处于排序状态。因此查看“键”和“键值对”时,全部获得的结果都是通过排序的,次序由天然排序或提供的Comparator决定。SortedMap接口拥有其余额外的功能,如:返回当前Map使用的Comparator比较器,firstKey(),lastKey(),headMap(toKey),tailMap(fromKey)以及能够返回一个子树的subMap()方法等。
WeakHashMap,表示弱键映射,WeakHashMap 的工做与正常的 HashMap 相似,可是使用弱引用做为 key,意思就是当 key 对象没有任何引用时,key/value 将会被回收。
ConcurrentHashMap, 在HashMap基础上分段锁机制实现的线程安全的HashMap。
IdentityHashMap 使用==代替equals() 对“键”进行比较的散列映射。专为解决特殊问题而设计。
HashTable:基于Dictionary类的Map接口的实现,它是线程安全的。
3.9 LinkedList 和 PriorityQueue 的区别
它们均是Queue接口的实现。拥有FIFO的特色,它们的区别在于排序行为。LinkedList 支持双向列表操做,PriorityQueue 按优先级组织的队列,元素的出队次序由元素的天然排序或者由Comparator比较器指定。
3.10 线程安全的集合类。Vector、Hashtable、Properties和Stack、ConcurrentHashMap
3.11 BlockingQueue
java.util.concurrent.BlockingQueue是一个队列,在进行获取元素时,它会等待队列变为非空;当在添加一个元素时,它会等待队列中的可用空间。BlockingQueue接口是Java集合框架的一部分,主要用于实现生产者-消费者模式。咱们不须要担忧等待生产者有可用的空间,或消费者有可用的对象,由于它都在BlockingQueue的实现类中被处理了。Java提供了集中BlockingQueue的实现,好比ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,、SynchronousQueue等。
3.12 如何对一组对象进行排序
若是须要对一个对象数组进行排序,咱们可使用Arrays.sort()方法。若是咱们须要排序一个对象列表,咱们可使用Collections.sort()方法。排序时是默认根据元素的天然排序(使用Comparable)或使用Comparator外部比较器。Collections内部使用数组排序方法,全部它们二者都有相同的性能,只是Collections须要花时间将列表转换为数组。
4. ArrayList
5. final关键字
final
修饰的变量是常量,必须进行初始化,能够显示初始化,也能够经过构造函数进行初始化,若是不初始化编译会报错。
6. 接口与抽象类
6.1 一个子类只能继承一个抽象类,但能实现多个接口6.2 抽象类能够有构造方法,接口没有构造方法6.3 抽象类能够有普通成员变量,接口没有普通成员变量6.4 抽象类和接口均可有静态成员变量,抽象类中静态成员变量访问类型任意,接口只能public static final(默认)6.5 抽象类能够没有抽象方法,抽象类能够有普通方法,接口中都是抽象方法6.6 抽象类能够有静态方法,接口不能有静态方法6.7 抽象类中的方法能够是public、protected;接口方法只有public abstract
7. 抽象类和最终类
抽象类能够没有抽象方法, 最终类能够没有最终方法
最终类不能被继承, 最终方法不能被重写(能够重载)
8.异常
相关的关键字 throw、throws、try...catch、finally
9. 关于finally
注意:finally中最好不要包含return,不然程序会提早退出,返回值不是try或catch中保存的返回值
finally不执行的几种状况:程序提早终止如调用了System.exit, 病毒,断电
10. 受检查异常和运行时异常
10.1 粉红色的是受检查的异常(checked exceptions),其必须被try...catch语句块所捕获, 或者在方法签名里经过throws子句声明。受检查的异常必须在编译时被捕捉处理,命名为Checked Exception是由于Java编译器要进行检查, Java虚拟机也要进行检查, 以确保这个规则获得遵照。
常见的checked exception:ClassNotFoundException IOException FileNotFoundException EOFException
10.2 绿色的异常是运行时异常(runtime exceptions), 须要程序员本身分析代码决定是否捕获和处理,好比空指针,被0除...
常见的runtime exception:NullPointerException ArithmeticException ClassCastException IllegalArgumentException IllegalStateException IndexOutOfBoundsException NoSuchElementException
10.3 而声明为Error的,则属于严重错误,如系统崩溃、虚拟机错误、动态连接失败等,这些错误没法恢复或者不可能捕捉,将致使应用程序中断,Error不须要捕获。
11. this & super
11.1 super出如今父类的子类中。有三种存在方式
注:super只能指代其直接父类
11.2 this() & super()在构造方法中的区别
12. 修饰符一览
修饰符 类内部 同一个包 子类 任何地方
private yes
default yes yes
protected yes yes yes
public yes yes yes yes复制代码
13. 内部类和静态内部类
public class Enclosingone {
public class Insideone {}
public static class Insideone{}
}
public class Test {
public static void main(String[] args) {
// 构造内部类对象须要外部类的引用
Enclosingone.Insideone obj1 = new Enclosingone().new Insideone();
// 构造静态内部类的对象
Enclosingone.Insideone obj2 = new Enclosingone.Insideone();
}
}复制代码
静态内部类不须要有指向外部类的引用。但非静态内部类须要持有对外部类的引用。非静态内部类可以访问外部类的静态和非静态成员。静态内部类不能访问外部类的非静态成员,只能访问外部类的静态成员。
14. 序列化
声明为static和transient类型的数据不能被序列化, 反序列化须要一个无参构造函数
序列化参见个人笔记Java-note-序列化.md
15.正则表达式
次数符号
* 0或屡次
+ 1或屡次
?0或1次
{n} 恰n次
{n,m} 从n到m次复制代码
其余符号
符号 等价形式
\d [0-9]
\D [^0-9]
\w [a-zA-Z_0-9]
\W [^a-zA-Z_0-9]
\s [\t\n\r\f]
\S [^\t\n\r\f]
. 任何字符复制代码
边界匹配器
行开头 ^行结尾 $单词边界 b
贪婪模式:最大长度匹配 非贪婪模式:匹配到结果就好,最短匹配
环视
字符 描述 匹配对象
. 单个任意字符
[...] 字符组 列出的任意字符
[^...] 未列出的任意字符
^ caret 行的起始位置
$ dollar 行的结束位置
\< 单词的起始位置
\> 单词的结束位置
\b 单词边界
\B 非单词边界
(?=Expression) 顺序确定环视 成功,若是右边可以匹配
(?!Expression) 顺序否认环视 成功,若是右边不可以匹配
(?<=Expression) 逆序确定环视 成功,若是左边可以匹配
(?<!Expression) 逆序否认环视 成功,若是左边不可以匹配复制代码
举例:北京市(海淀区)(朝阳区)(西城区)
Regex: .*(?=\()
模式和匹配器的典型调用次序
16. 面向对象的五大基本原则(solid)
SRP
:Single-Responsibility PrincipleOCP
:Open-Closed PrincipleLSP
:Liskov-Substitution PrincipleISP
:Interface-Segregation PrincipleDIP
:Dependency-Inversion Principle17. 面向对象设计其余原则
说明:一个对象应当对其余对象有尽量少的了解,将方法调用保持在界限内,只调用属于如下范围的方法:该对象自己(本地方法)对象的组件 被看成方法参数传进来的对象 此方法建立或实例化的任何对象
18. null能够被强制转型为任意类型的对象
19.代码执行次序
20. 数组复制方法
21. 多态
22. Java文件
java文件能够包含多个类,惟一的限制就是:一个文件中只能有一个public类, 而且此public类必须与文件名相同。并且这些类和写在多个文件中没有区别。
23. Java移位运算符
java中有三种移位运算符
<<
:左移运算符,x << 1,至关于x乘以2(不溢出的状况下),低位补0 >>
:带符号右移,x >> 1,至关于x除以2,正数高位补0,负数高位补1 >>>
:无符号右移,忽略符号位,空位都以0补齐 参见个人GitHub,Java移位符
24. 形参&实参
25. IO流一览
26. 局部变量为何要初始化
局部变量是指类方法中的变量,必须初始化。局部变量运行时被分配在栈中,量大,生命周期短,若是虚拟机给每一个局部变量都初始化一下,是一笔很大的开销,但变量不初始化为默认值就使用是不安全的。出于速度和安全性两个方面的综合考虑,解决方案就是虚拟机不初始化,但要求编写者必定要在使用前给变量赋值。
27. Java语言的鲁棒性
Java在编译和运行程序时,都要对可能出现的问题进行检查,以消除错误的产生。它提供自动垃圾收集来进行内存管理,防止程序员在管理内存时容易产生的错误。经过集成的面向对象的例外处理机制,在编译时,Java揭示出可能出现但未被处理的异常,帮助程序员正确地进行选择以防止系统的崩溃。另外,Java在编译时还可捕获类型声明中的许多常见错误,防止动态运行时不匹配问题的出现。
28. Java语言特性
29. 包装类的equals()方法不处理数据转型,必须类型和值都同样才相等。
30. 子类能够继承父类的静态方法!可是不能覆盖。由于静态方法是在编译时肯定了,不能多态,也就是不能运行时绑定。
31. Java语法糖
32. Java 中应该使用什么数据类型来表明价格?
若是不是特别关心内存和性能的话,使用BigDecimal,不然使用预约义精度的 double 类型。
33. 怎么将 byte 转换为 String?
可使用 String 接收 byte[] 参数的构造器来进行转换,须要注意的点是要使用的正确的编码,不然会使用平台默认编码,这个编码可能跟原来的编码相同,也可能不一样。
34. Java 中怎样将 bytes 转换为 long 类型?
String接收bytes的构造器转成String,再Long.parseLong
35. 咱们能将 int 强制转换为 byte 类型的变量吗?若是该值大于 byte 类型的范围,将会出现什么现象?
是的,咱们能够作强制转换,可是 Java 中 int 是 32 位的,而 byte 是 8 位的,因此,若是强制转化是,int 类型的高 24 位将会被丢弃,byte 类型的范围是从 -128 到 127。
36. 存在两个类,B 继承 A,C 继承 B,咱们能将 B 转换为 C 么?如 C = (C) B;
能够,向下转型。可是不建议使用,容易出现类型转型异常.
37. 哪一个类包含 clone 方法?是 Cloneable 仍是 Object?
java.lang.Cloneable 是一个标示性接口,不包含任何方法,clone 方法在 Object 类中定义。而且须要知道 clone() 方法是一个本地方法,这意味着它是由 c 或 c++ 或 其余本地语言实现的。
38. Java 中 ++ 操做符是线程安全的吗?
不是线程安全的操做。它涉及到多个指令,如读取变量值,增长,而后存储回内存,这个过程可能会出现多个线程交差。还会存在竞态条件(读取-修改-写入)。
39. a = a + b 与 a += b 的区别
+= 隐式的将加操做的结果类型强制转换为持有结果的类型。若是两这个整型相加,如 byte、short 或者 int,首先会将它们提高到 int 类型,而后在执行加法操做。
byte a = 127;
byte b = 127;
b = a + b; // error : cannot convert from int to byte
b += a; // ok
复制代码
(由于 a+b 操做会将 a、b 提高为 int 类型,因此将 int 类型赋值给 byte 就会编译出错)
40. 我能在不进行强制转换的状况下将一个 double 值赋值给 long 类型的变量吗?
不行,你不能在没有强制类型转换的前提下将一个 double 值赋值给 long 类型的变量,由于 double 类型的范围比 long 类型更广,因此必需要进行强制转换。
41. 3*0.1 == 0.3 将会返回什么?true 仍是 false?
false,由于有些浮点数不能彻底精确的表示出来。
42. int 和 Integer 哪一个会占用更多的内存?
Integer 对象会占用更多的内存。Integer 是一个对象,须要存储对象的元数据。可是 int 是一个原始类型的数据,因此占用的空间更少。
43. 为何 Java 中的 String 是不可变的(Immutable)?
Java 中的 String 不可变是由于 Java 的设计者认为字符串使用很是频繁,将字符串设置为不可变能够容许多个客户端之间共享相同的字符串。
44. 咱们能在 Switch 中使用 String 吗?
从 Java 7 开始,咱们能够在 switch case 中使用字符串,但这仅仅是一个语法糖。内部实如今 switch 中使用字符串的 hash code。
45. Java 中的构造器链是什么?
当你从一个构造器中调用另外一个构造器,就是Java 中的构造器链。这种状况只在重载了类的构造器的时候才会出现。
46. 枚举类
JDK1.5出现 每一个枚举值都须要调用一次构造函数。
48. 什么是不可变对象(immutable object)?Java 中怎么建立一个不可变对象?
不可变对象指对象一旦被建立,状态就不能再改变。任何修改都会建立一个新的对象,如 String、Integer及其它包装类。
如何在Java中写出Immutable的类?
要写出这样的类,须要遵循如下几个原则:
1)immutable对象的状态在建立以后就不能发生改变,任何对它的改变都应该产生一个新的对象。
2)Immutable类的全部的属性都应该是final的。
3)对象必须被正确的建立,好比:对象引用在对象建立过程当中不能泄露(leak)。
4)对象应该是final的,以此来限制子类继承父类,以免子类改变了父类的immutable特性。
5)若是类中包含mutable类对象,那么返回给客户端的时候,返回该对象的一个拷贝,而不是该对象自己(该条能够归为第一条中的一个特例)
49. 咱们能建立一个包含可变对象的不可变对象吗?
是的,咱们是能够建立一个包含可变对象的不可变对象的,你只须要谨慎一点,不要共享可变对象的引用就能够了,若是须要变化时,就返回原对象的一个拷贝。最多见的例子就是对象中包含一个日期对象的引用。
50. List和Set
List 是一个有序集合,容许元素重复。它的某些实现能够提供基于下标值的常量访问时间,可是这不是 List 接口保证的。Set 是一个无序集合。
51. poll() 方法和 remove() 方法的区别?
poll() 和 remove() 都是从队列中取出一个元素,可是 poll() 在获取元素失败的时候会返回空,可是 remove() 失败的时候会抛出异常。
52. Java 中 LinkedHashMap 和 PriorityQueue 的区别是什么?
PriorityQueue 保证最高或者最低优先级的的元素老是在队列头部,可是 LinkedHashMap 维持的顺序是元素插入的顺序。当遍历一个 PriorityQueue 时,没有任何顺序保证,可是 LinkedHashMap 课保证遍历顺序是元素插入的顺序。
53. ArrayList 与 LinkedList 的区别?
最明显的区别是 ArrrayList 底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构书链表,不支持随机访问。使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。
54. 用哪两种方式来实现集合的排序?
你可使用有序集合,如 TreeSet 或 TreeMap,你也可使用有顺序的的集合,如 List,而后经过 Collections.sort() 来排序。
55. Java 中怎么打印数组?
你可使用 Arrays.toString() 和 Arrays.deepToString() 方法来打印数组。因为数组没有实现 toString() 方法,因此若是将数组传递给 System.out.println() 方法,将没法打印出数组的内容,可是 Arrays.toString() 能够打印每一个元素。
56. Java 中的 LinkedList 是单向链表仍是双向链表?
是双向链表,你能够检查 JDK 的源码。在 Eclipse,你可使用快捷键 Ctrl + T,直接在编辑器中打开该类。
57. Java 中的 TreeMap 是采用什么树实现的?
Java 中的 TreeMap 是使用红黑树实现的。
58. Java 中的 HashSet,内部是如何工做的?
HashSet 的内部采用 HashMap来实现。因为 Map 须要 key 和 value,因此全部 key 的都有一个默认 value。相似于 HashMap,HashSet 不容许重复的 key,只容许有一个null key,意思就是 HashSet 中只容许存储一个 null 对象。
59. 写一段代码在遍历 ArrayList 时移除一个元素?
该问题的关键在于面试者使用的是 ArrayList 的 remove() 仍是 Iterator 的 remove()方法。后者是正确的方式不会出现 ConcurrentModificationException 异常。
60. 咱们能本身写一个容器类,而后使用 for-each 循环吗?
能够,你能够写一个本身的容器类。若是你想使用 Java 中加强的循环来遍历,你只须要实现 Iterable 接口。若是你实现 Collection 接口,默认就具备该属性。
61. ArrayList 和 HashMap 的默认大小是多数?
在 Java 7 中,ArrayList 的默认大小是 10 个元素,HashMap 的默认大小是16个元素(必须是2的幂)。这就是 Java 7 中 ArrayList 和 HashMap 类的代码片断:
// from ArrayList.java JDK 1.7
private static final int DEFAULT_CAPACITY = 10;
//from HashMap.java JDK 7
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 16复制代码
62. 有没有可能两个不相等的对象有有相同的 hashcode?
有可能,两个不相等的对象可能会有相同的 hashcode 值,这就是为何在 hashmap 中会有冲突。相等 hashcode 值的规定只是说若是两个对象相等,必须有相同的hashcode 值,可是没有关于不相等对象的任何规定。
63. 两个相同的对象会有不一样的的 hash code 吗?
不能,根据 hash code 的规定,这是不可能的。
64. 咱们能够在 hashcode() 中使用随机数字吗?
不行,由于对象的 hashcode 值必须是相同的。
65. Java 中,Comparator 与 Comparable 有什么不一样?
Comparable 接口用于定义对象的天然顺序,而 comparator 一般用于定义用户定制的顺序。Comparable 老是只有一个,可是能够有多个 comparator 来定义对象的顺序。
66. 为何在重写 equals 方法的时候须要重写 hashCode 方法?
由于有强制的规范指定须要同时重写 hashcode 与 equal 方法,许多容器类,如 HashMap、HashSet 都依赖于 hashcode 与 equals 的规定。
67. “a==b”和”a.equals(b)”有什么区别?
若是 a 和 b 都是对象,则 a==b 是比较两个对象的引用,只有当 a 和 b 指向的是堆中的同一个对象才会返回 true,而 a.equals(b) 是进行逻辑比较,因此一般须要重写该方法来提供逻辑一致性的比较。例如,String 类重写 equals() 方法,因此能够用于两个不一样对象,可是包含的字母相同的比较。
68. a.hashCode() 有什么用?与 a.equals(b) 有什么关系?
简介:hashCode() 方法是相应对象整型的 hash 值。它经常使用于基于 hash 的集合类,如 Hashtable、HashMap、LinkedHashMap等等。它与 equals() 方法关系特别紧密。根据 Java 规范,两个使用 equal() 方法来判断相等的对象,必须具备相同的 hash code。
一、hashcode的做用
List和Set,如何保证Set不重复呢?经过迭代使用equals方法来判断,数据量小还能够接受,数据量大怎么解决?引入hashcode,实际上hashcode扮演的角色就是寻址,大大减小查询匹配次数。
二、hashcode重要吗
对于数组、List集合就是一个累赘。而对于HashMap, HashSet, Hashtable就异常重要了。
三、equals方法遵循的原则
二者的关系
69. final、finalize 和 finally 的不一样之处?
final 是一个修饰符,能够修饰变量、方法和类。若是 final 修饰变量,意味着该变量的值在初始化后不能被改变。Java 技术容许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去以前作必要的清理工做。这个方法是由垃圾收集器在肯定这个对象没有被引用时对这个对象调用的,可是何时调用 finalize 没有保证。finally 是一个关键字,与 try 和 catch 一块儿用于异常的处理。finally 块必定会被执行,不管在 try 块中是否有发生异常。
70. Java 中的编译期常量是什么?使用它又什么风险?
变量也就是咱们所说的编译期常量,这里的 public 可选的。实际上这些变量在编译时会被替换掉,由于编译器知道这些变量的值,而且知道这些变量在运行时不能改变。这种方式存在的一个问题是你使用了一个内部的或第三方库中的公有编译时常量,可是这个值后面被其余人改变了,可是你的客户端仍然在使用老的值,甚至你已经部署了一个新的jar。为了不这种状况,当你在更新依赖 JAR 文件时,确保从新编译你的程序。
71. 说出几点 Java 中使用 Collections 的最佳实践
这是我在使用 Java 中 Collectionc 类的一些最佳实践:
a)使用正确的集合类,例如,若是不须要同步列表,使用 ArrayList 而不是 Vector。
b)优先使用并发集合,而不是对集合进行同步。并发集合提供更好的可扩展性。
c)使用接口表明和访问集合,如使用List存储 ArrayList,使用 Map 存储 HashMap 等等。
d)使用迭代器来循环集合。
e)使用集合的时候使用泛型。
72. 静态内部类与顶级类有什么区别?
一个公共的顶级类的源文件名称与类名相同,而嵌套静态类没有这个要求。一个嵌套类位于顶级类内部,须要使用顶级类的名称来引用嵌套静态类,如 HashMap.Entry 是一个嵌套静态类,HashMap 是一个顶级类,Entry是一个嵌套静态类。
73. Java 中,Serializable 与 Externalizable 的区别?
Serializable 接口是一个序列化 Java 类的接口,以便于它们能够在网络上传输或者能够将它们的状态保存在磁盘上,是 JVM 内嵌的默认序列化方式,成本高、脆弱并且不安全。Externalizable 容许你控制整个序列化过程,指定特定的二进制格式,增长安全机制。
74. 说出 JDK 1.7 中的三个新特性?
虽然 JDK 1.7 不像 JDK 5 和 8 同样的大版本,可是,仍是有不少新的特性,如 try-with-resource 语句,这样你在使用流或者资源的时候,就不须要手动关闭,Java 会自动关闭。Fork-Join 池某种程度上实现 Java 版的 Map-reduce。容许 Switch 中有 String 变量和文本。菱形操做符(<>)用于泛型推断,再也不须要在变量声明的右边申明泛型,所以能够写出可读写更强、更简洁的代码。另外一个值得一提的特性是改善异常处理,如容许在同一个 catch 块中捕获多个异常。
75. 说出 5 个 JDK 1.8 引入的新特性?
Java 8 在 Java 历史上是一个开创新的版本,下面 JDK 8 中 5 个主要的特性:Lambda 表达式,容许像对象同样传递匿名函数Stream API,充分利用现代多核 CPU,能够写出很简洁的代码Date 与 Time API,最终,有一个稳定、简单的日期和时间库可供你使用扩展方法,如今,接口中能够有静态、默认方法。重复注解,如今你能够将相同的注解在同一类型上使用屡次。
下述包含 Java 面试过程当中关于 SOLID 的设计原则,OOP 基础,如类,对象,接口,继承,多态,封装,抽象以及更高级的一些概念,如组合、聚合及关联。也包含了 GOF 设计模式的问题。
76. 接口是什么?为何要使用接口而不是直接使用具体类?
接口用于定义 API。它定义了类必须得遵循的规则。同时,它提供了一种抽象,由于客户端只使用接口,这样能够有多重实现,如 List 接口,你可使用可随机访问的 ArrayList,也可使用方便插入和删除的 LinkedList。接口中不容许普通方法,以此来保证抽象,可是 Java 8 中你能够在接口声明静态方法和默认普通方法。
77. Java 中,抽象类与接口之间有什么不一样?
Java 中,抽象类和接口有不少不一样之处,可是最重要的一个是 Java 中限制一个类只能继承一个类,可是能够实现多个接口。抽象类能够很好的定义一个家族类的默认行为,而接口能更好的定义类型,有助于后面实现多态机制参见第六条。
78. 除了单例模式,你在生产环境中还用过什么设计模式?
这须要根据你的经验来回答。通常状况下,你能够说依赖注入,工厂模式,装饰模式或者观察者模式,随意选择你使用过的一种便可。不过你要准备回答接下的基于你选择的模式的问题。
79. 你能解释一下里氏替换原则吗?
严格定义:若是对每个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的全部程序P在全部的对象用o1替换o2时,程序P的行为没有变化,那么类型S是类型T的子类型。
通俗表述:全部引用基类(父类)的地方必须能透明地使用其子类的对象。也就是说子类能够扩展父类的功能,但不能改变父类原有的功能。它包含如下4层含义:
80.什么状况下会违反迪米特法则?为何会有这个问题?
迪米特法则建议“只和朋友说话,不要陌生人说话”,以此来减小类之间的耦合。
81. 适配器模式是什么?何时使用?
适配器模式提供对接口的转换。若是你的客户端使用某些接口,可是你有另一些接口,你就能够写一个适配去来链接这些接口。
82. 构造器注入和 setter 依赖注入,那种方式更好?
每种方式都有它的缺点和优势。构造器注入保证全部的注入都被初始化,可是 setter 注入提供更好的灵活性来设置可选依赖。若是使用 XML 来描述依赖,Setter 注入的可读写会更强。经验法则是强制依赖使用构造器注入,可选依赖使用 setter 注入。
83. 依赖注入和工厂模式之间有什么不一样?
虽然两种模式都是将对象的建立从应用的逻辑中分离,可是依赖注入比工程模式更清晰。经过依赖注入,你的类就是 POJO,它只知道依赖而不关心它们怎么获取。使用工厂模式,你的类须要经过工厂来获取依赖。所以,使用 DI 会比使用工厂模式更容易测试。
84. 适配器模式和装饰器模式有什么区别?
虽然适配器模式和装饰器模式的结构相似,可是每种模式的出现意图不一样。适配器模式被用于桥接两个接口,而装饰模式的目的是在不修改类的状况下给类增长新的功能。
85. 适配器模式和代理模式以前有什么不一样?
这个问题与前面的相似,适配器模式和代理模式的区别在于他们的意图不一样。因为适配器模式和代理模式都是封装真正执行动做的类,所以结构是一致的,可是适配器模式用于接口之间的转换,而代理模式则是增长一个额外的中间层,以便支持分配、控制或智能访问。
86. 什么是模板方法模式?
模板方法提供算法的框架,你能够本身去配置或定义步骤。例如,你能够将排序算法看作是一个模板。它定义了排序的步骤,可是具体的比较,可使用 Comparable 或者其语言中相似东西,具体策略由你去配置。列出算法概要的方法就是众所周知的模板方法。
87. 何时使用访问者模式?
访问者模式用于解决在类的继承层次上增长操做,可是不直接与之关联。这种模式采用双派发的形式来增长中间层。
88. 何时使用组合模式?
组合模式使用树结构来展现部分与总体继承关系。它容许客户端采用统一的形式来对待单个对象和对象容器。当你想要展现对象这种部分与总体的继承关系时采用组合模式。
89. 继承和组合之间有什么不一样?
虽然两种均可以实现代码复用,可是组合比继承共灵活,由于组合容许你在运行时选择不一样的实现。用组合实现的代码也比继承测试起来更加简单。
90. 描述 Java 中的重载和重写?
重载和重写都容许你用相同的名称来实现不一样的功能,可是重载是编译时活动,而重写是运行时活动。你能够在同一个类中重载方法,可是只能在子类中重写方法。重写必需要有继承。
91. OOP 中的 组合、聚合和关联有什么区别?
若是两个对象彼此有关系,就说他们是彼此相关联的。组合和聚合是面向对象中的两种形式的关联。组合是一种比聚合更强力的关联。组合中,一个对象是另外一个的拥有者,而聚合则是指一个对象使用另外一个对象。若是对象 A 是由对象 B 组合的,则 A 不存在的话,B必定不存在,可是若是 A 对象聚合了一个对象 B,则即便 A 不存在了,B 也能够单独存在。
92. 给我一个符合开闭原则的设计模式的例子?
开闭原则要求你的代码对扩展开放,对修改关闭。这个意思就是说,若是你想增长一个新的功能,你能够很容易的在不改变已测试过的代码的前提下增长新的代码。有好几个设计模式是基于开闭原则的,如策略模式,若是你须要一个新的策略,只须要实现接口,增长配置,不须要改变核心逻辑。一个正在工做的例子是 Collections.sort() 方法,这就是基于策略模式,遵循开闭原则的,你不需为新的对象修改 sort() 方法,你须要作的仅仅是实现你本身的 Comparator 接口。
93. 何时使用享元模式(蝇量模式)?
享元模式经过共享对象来避免建立太多的对象。为了使用享元模式,你须要确保你的对象是不可变的,这样你才能安全的共享。JDK 中 String 池、Integer 池以及 Long 池都是很好的使用了享元模式的例子。
94. Java 中如何格式化一个日期?如格式化为 ddMMyyyy 的形式?
Java 中,可使用 SimpleDateFormat 类或者 joda-time 库来格式日期。DateFormat 类容许你使用多种流行的格式来格式化日期。
95. Java 中,怎么在格式化的日期中显示时区?
pattern中加z yyyy-MM-dd HH:mm:ss.SSS Z
96. Java 中 java.util.Date 与 java.sql.Date 有什么区别?
java.sql.Date是针对SQL语句使用的,它只包含日期而没有时间部分,它们都有getTime方法返回毫秒数,天然就能够直接构建。java.util.Date 是 java.sql.Date 的父类,前者是经常使用的表示时间的类,咱们一般格式化或者获得当前时间都是用他,后者以后在读写数据库的时候用他,由于PreparedStament的setDate()的第2参数和ResultSet的getDate()方法的第2个参数都是java.sql.Date。
97. Java 中,如何计算两个日期之间的差距?
public static int dateDiff(Date d1, Date d2) throws Exception {
long n1 = d1.getTime();
long n2 = d2.getTime();
long diff = Math.abs(n1 - n2);
diff /= 3600 * 1000 * 24;
return diff;
}复制代码
98. Java 中,如何将字符串 YYYYMMDD 转换为日期?
SimpleDateFormat的parse方法
99. 说出几条 Java 中方法重载的最佳实践?
下面有几条能够遵循的方法重载的最佳实践来避免形成自动装箱的混乱。
a)不要重载这样的方法:一个方法接收 int 参数,而另个方法接收 Integer 参数。
b)不要重载参数数量一致,而只是参数顺序不一样的方法。
c)若是重载的方法参数个数多于 5 个,采用可变参数。
100. 说出 5 条 IO 的最佳实践
IO 对 Java 应用的性能很是重要。理想状况下,你应该在你应用的关键路径上避免 IO 操做。下面是一些你应该遵循的 Java IO 最佳实践:
a)使用有缓冲区的 IO 类,而不要单独读取字节或字符
b)使用 NIO 和 NIO2
c)在 finally 块中关闭流,或者使用 try-with-resource(Java7) 语句
d)使用内存映射文件获取更快的 IO
101. Object有哪些公用方法?
clone equals hashcode wait notify notifyall finalize toString getClass除了clone和finalize其余均为public方法。
11个方法,wait被重载了两次
102. equals与==的区别
区别1. ==是一个运算符 equals是Object类的方法
区别2. 比较时的区别
a. 用于基本类型的变量比较时:==用于比较值是否相等,equals不能直接用于基本数据类型的比较,须要转换为其对应的包装类型。b. 用于引用类型的比较时。==和equals都是比较栈内存中的地址是否相等 。相等为true 不然为false。可是一般会重写equals方法去实现对象内容的比较。
103. String、StringBuffer与StringBuilder的区别
第一点:可变和适用范围。String对象是不可变的,而StringBuffer和StringBuilder是可变字符序列。每次对String的操做至关于生成一个新的String对象,而对StringBuffer和StringBuilder的操做是对对象自己的操做,而不会生成新的对象,因此对于频繁改变内容的字符串避免使用String,由于频繁的生成对象将会对系统性能产生影响。
第二点:线程安全。String因为有final修饰,是immutable的,安全性是简单而纯粹的。StringBuilder和StringBuffer的区别在于StringBuilder不保证同步,也就是说若是须要线程安全须要使用StringBuffer,不须要同步的StringBuilder效率更高。
104. switch可否用String作参数
Java1.7开始支持,但实际这是一颗Java语法糖。除此以外,byte,short,long,枚举,boolean都可用于switch,只有浮点型不能够。
105. 封装、继承、多态
封装:
1.概念:就是把对象的属性和操做(或服务)结合为一个独立的总体,并尽量隐藏对象的内部实现细节。
2.好处:
(1)隐藏内部实现细节。
继承:
1.概念:继承是从已有的类中派生出新的类,新的类能吸取已有类的数据属性和行为,并能扩展新的能力
2.好处:提升代码的复用,缩短开发周期。
多态:
1.概念:多态(Polymorphism)按字面的意思就是“多种状态,即同一个实体同时具备多种形式。通常表现形式是程序在运行的过程当中,同一种类型在不一样的条件下表现不一样的结果。多态也称为动态绑定,通常是在运行时刻才能肯定方法的具体执行对象。
2.好处:
1)将接口和实现分开,改善代码的组织结构和可读性,还能建立可拓展的程序。
2)消除类型之间的耦合关系。容许将多个类型视为同一个类型。
3)一个多态方法的调用容许有多种表现形式
106. Comparable和Comparator接口区别
Comparator位于包java.util下,而Comparable位于包java.lang下
若是咱们须要使用Arrays或Collections的排序方法对对象进行排序时,咱们须要在自定义类中实现Comparable接口并重写compareTo方法,compareTo方法接收一个参数,若是this对象比传递的参数小,相等或大时分别返回负整数、0、正整数。Comparable被用来提供对象的天然排序。String、Integer实现了该接口。
Comparator比较器的compare方法接收2个参数,根据参数的比较大小分别返回负整数、0和正整数。Comparator 是一个外部的比较器,当这个对象天然排序不能知足你的要求时,你能够写一个比较器来完成两个对象之间大小的比较。用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。
107. 与Java集合框架相关的有哪些最好的实践
(1)根据须要选择正确的集合类型。好比,若是指定了大小,咱们会选用Array而非ArrayList。若是咱们想根据插入顺序遍历一个Map,咱们须要使用TreeMap。若是咱们不想重复,咱们应该使用Set。
(2)一些集合类容许指定初始容量,因此若是咱们可以估计到存储元素的数量,咱们可使用它,就避免了从新哈希或大小调整。
(3)基于接口编程,而非基于实现编程,它容许咱们后来轻易地改变实现。
(4)老是使用类型安全的泛型,避免在运行时出现ClassCastException。
(5)使用JDK提供的不可变类做为Map的key,能够避免本身实现hashCode()和equals()。
108. IO和NIO简述
一、简述
在之前的Java IO中,都是阻塞式IO,NIO引入了非阻塞式IO。第一种方式:我从硬盘读取数据,而后程序一直等,数据读完后,继续操做。这种方式是最简单的,叫阻塞IO。第二种方式:我从硬盘读取数据,而后程序继续向下执行,等数据读取完后,通知当前程序(对硬件来讲叫中断,对程序来讲叫回调),而后此程序能够当即处理数据,也能够执行完当前操做在读取数据。
2.流与块的比较
原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。面向流 的 I/O 系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。这样作是相对简单的。不利的一面是,面向流的 I/O 一般至关慢。一个 面向块 的 I/O 系统以块的形式处理数据。每个操做都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。可是面向块的 I/O 缺乏一些面向流的 I/O 所具备的优雅性和简单性。
3.通道与流
Channel是一个对象,能够经过它读取和写入数据。通道与流功能相似,不一样之处在于通道是双向的。而流只是在一个方向上移动(一个流必须是 InputStream 或者 OutputStream 的子类), 而通道能够用于读、写或者同时用于读写。
4.缓冲区Buffer
在 NIO 库中,全部数据都是用缓冲区处理的。
Position: 表示下一次访问的缓冲区位置
Limit: 表示当前缓冲区存放的数据容量。
Capacity:表示缓冲区最大容量
flip()方法:读写模式切换
clear方法:它将 limit 设置为与 capacity 相同。它设置 position 为 0。复制代码
【感谢您能看完,若是可以帮到您,麻烦点个赞~】
更多经验技术欢迎前来共同窗习交流:一点课堂-为梦想而奋斗的在线学习平台 http://www.yidiankt.com/
![关注公众号,回复“1”免费领取-【java核心知识点】]
QQ讨论群:616683098
QQ:3184402434
想要深刻学习的同窗们能够加我QQ一块儿学习讨论~还有全套资源分享,经验探讨,等你哦!