0、问题大纲
一、Java 基础
1.2 方法操作
1、== 和 Equals的区别,如果重写了Equals()不重写HashCode()会发生什么?
2、Java有个最基本的类Object,这个类默认包含哪几个方法?
3、对比Vector、ArrayList、LinkedList有何区别?【第8讲】(*4)
- 追问1:是不是线程安全的?
- 追问2:各自应用场景是什么?
4、对比Hashtable、HashMap、TreeMap有什么不同?【第9讲】(*3)
- 更多:……
// 接HashMap之追问系列
1、为什么是 0.75 这个值呢?
2、什么办法来解决因链表过长导致查询时间复杂度高的问题呢?
3、影响 HashMap 性能的因素?
4、HashMap的哈希函数怎么设计的?
- 追问1:初始容量为什么设置为 2 的整数次幂?【(n - 1) & hash 】
- 追问2:如果没使用 hash() 方法计算 hashCode,直接使用对象的 hashCode 值,会出现什么问题呢?
- 追问3:为什么获取下标时用按位与 &,而不是取模 %?
5、JDK1.8后对HashMap的改进(*3)
- 追问1:为什么要做这几点优化?
- 追问2:1.8 中的 HashMap 是否线程安全?
- 追问3:什么时机执行 resize()?
- 追问4:resize() 如何实现的?
6、HashMap get和put源码,
7、HashMap 的 key 需要满足什么条件?
- 追问1:HashMap 允许 key/value 为 null, 但最多只有一个。 为什么?
- 追问2:如果重写了equals(),不重写hashCode()会发生什么?
8、你平常怎么解决这个线程不安全的问题?
9、那你知道ConcurrentHashMap的分段锁的实现原理吗?
5、HashSet底层实现?
- 追问1:线程安全吗?
6、Java提供了哪些IO方式(*2)? NIO如何实现多路复用?【第11讲】
7、Java有几种文件拷贝方式?哪一种最高效?【第12讲】
8、写正则表达式进行手机号匹配(*2)。
一、Java 基础
1、== 和 Equals的区别?
==
:基本数据类型:比较值;引用数据类型:比较对象的(堆)内存地址内存。
equals
:默认是引用比较,很多类(String、Integer)重写 equals,变成了值比较。
// 举例:
public class StringDemo {
public static void main(String args[]) {
String str1 = "Hello";
String str2 = new String("Hello"); // 开辟新的堆内存
String str3 = str2; // 引用传递
System.out.println(str1 == str2); // false
System.out.println(str1 == str3); // false
System.out.println(str2 == str3); // true
System.out.println(str1.equals(str2)); // true
System.out.println(str1.equals(str3)); // true
System.out.println(str2.equals(str3)); // true
}
}
2、Java有个最基本的类Object,这个类默认包含哪几个方法?
函数名 | 功能 |
---|---|
registerNatives() | 对本地方法进行注册 |
getClass() | 返回一个对象的运行时类 |
hashCode() | 返回该对象的哈希值 |
equals() | 指示某个其他对象是否与此对象相等 |
clone() | 创建并返回此对象的一个副本 |
toString() | 返回该对象的字符串表示 |
notify() | 唤醒此对象监视器上等待的单个线程 |
notifyAll() | 唤醒此对象监视器上等待的所有线程 |
wait(long) | 导致当前线程等待调用此对象的notify()或notifyAll() |
wait(long,int) | 导致当前线程等待,直到其他线程调用此对象的notify()或notifyAll(),或其他某个线程中断当前线程,或已经超过某个实际时间量 |
wait() | 导致当前线程等待,直到其他线程调用此对象的notify()或notifyAll() |
finalize() | 当垃圾回收确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法 |
Object() | 默认构造方法 |
3、对比Vector、ArrayList、LinkedList有何区别?【第8讲】(*2):存储,线程,扩容
对象 | 存储 | 线程 | 扩容 |
---|---|---|---|
Vector | 动态数组 | Y | 100% |
ArrayList | 动态数组 | N | 50% |
LinkedList | 双向链表 | N | - |
追问1:各自应用场景是什么?
Vector 和 ArrayList 以数组形式顺序存储,所以非常适合随机访问。
LinkedList 进行插入、删除很高效,但随机访问比动态数组慢。
4、对比Hashtable、HashMap、TreeMap有什么不同?【第9讲】(*6)
Hashtable
是同步的哈希表实现,不支持 null 键和值。同步让开销更大,很少使用。
HashMap
是不同步的哈希表实现,支持 null 键和值等。put、get
操作通常可达到常数时间性能,是绝大部分键值对存取首选。
TreeMap
是基于红黑树的一种提供顺序访问的 Map
, get、put、remove
类操作时间复杂度是 O(logn)
,具体顺序由 指定Comparator 或 键的自然顺序
来决定。
补充:
1、相同:都是 Map 实现,是以键值对形式存储和操作数据的容器类型。
2、容器:存储元素的单元。这样来看,数据类型都是容器。
3、线程同步:多线程操作一个资源导致资源不一致,这需要协调资源的调度,即线程同步。
4、线程安全:多线程访问类X时,X都表现正确行为,则X是线程安全。 线程安全类封装了同步机制。
追问系列:
1、为什么是 0.75 这个值呢?
2、什么办法来解决因链表过长导致查询时间复杂度高的问题呢?
3、影响 HashMap 性能的因素?
4、HashMap的哈希函数怎么设计的?
- 追问1:初始容量为什么设置为 2 的整数次幂?【(n - 1) & hash 】
- 追问2:如果没使用 hash() 方法计算 hashCode,直接使用对象的 hashCode 值,会出现什么问题呢?
- 追问3:为什么获取下标时用按位与 &,而不是取模 %?
5、JDK1.8后对HashMap的改进(*3)
- 追问1:为什么要做这几点优化?
- 追问2:1.8 中的 HashMap 是否线程安全?
- 追问3:什么时机执行 resize()?
- 追问4:resize() 如何实现的?
6、HashMap get和put源码,
7、HashMap 的 key 需要满足什么条件?
- 追问1:HashMap 允许 key/value 为 null, 但最多只有一个。 为什么?
- 追问2:如果重写了equals(),不重写hashCode()会发生什么?
8、你平常怎么解决这个线程不安全的问题?
9、那你知道ConcurrentHashMap的分段锁的实现原理吗?
回答详解见:【疑惑整理】【Java】深入浅出HashMap+面试整理
5、HashSet底层实现?
在HashMap上包了一层,默认存储一个Object的静态常量,取时候也是只返回key。其中add方法调用HashMap的put()方法实现。
if key is existed, then 是旧值,失败;
if (map.put()==null), then 添加元素作为map.key
追问1:线程安全吗?
不安全,同HashMap。
6、Java提供了哪些IO方式(*2)? NIO如何实现多路复用?【第11讲】
Java IO 方式有很多种,基于不同的 IO 抽象模型和交互方式,可以进行简单区分。
首先,传统的 java.io 包,它基于流模型实现,提供了我们最熟知的一些 IO 功能,比如 File 抽象、输入输出流等。交互方式是同步、阻塞的方式,也就是说,在读取输入流或者写入输出流时,在读、写动作完成之前,线程会一直阻塞在那里,它们之间的调用是可靠的线性顺序。
java.io 包的好处是代码比较简单、直观,缺点则是 IO 效率和扩展性存在局限性,容易成为应用性能的瓶颈。
很多时候,人们也把 java.net 下面提供的部分网络 API,比如 Socket、ServerSocket、HttpURLConnection 也归类到同步阻塞 IO 类库,因为网络通信同样是 IO 行为。
第二,在 Java 1.4 中引入了 NIO 框架(java.nio 包),提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层的高性能数据操作方式。
第三,在 Java 7 中,NIO 有了进一步的改进,也就是 NIO 2,引入了异步非阻塞 IO 方式,也有很多人叫它 AIO(Asynchronous IO)。异步 IO 操作基于事件和回调机制,可以简单理解为,应用操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作。
7、Java有几种文件拷贝方式?哪一种最高效?【第12讲】
Java 有多种比较典型的文件拷贝实现方式,比如:
利用 java.io 类库,直接为源文件构建一个 FileInputStream 读取,然后再为目标文件构建一个 FileOutputStream,完成写入工作。
public static void copyFileByStream(File source, File dest) throws
IOException {
try (InputStream is = new FileInputStream(source);
OutputStream os = new FileOutputStream(dest);){
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
}
}
或者,利用 java.nio 类库提供的 transferTo 或 transferFrom 方法实现。
public static void copyFileByChannel(File source, File dest) throws
IOException {
try (FileChannel sourceChannel = new FileInputStream(source)
.getChannel();
FileChannel targetChannel = new FileOutputStream(dest).getChannel
();){
for (long count = sourceChannel.size() ;count>0 ;) {
long transferred = sourceChannel.transferTo(
sourceChannel.position(), count, targetChannel); sourceChannel.position(sourceChannel.position() + transferred);
count -= transferred;
}
}
}
当然,Java 标准类库本身已经提供了几种 Files.copy 的实现。
对于 Copy 的效率,这个其实与操作系统和配置等情况相关,总体上来说,NIO transferTo/From 的方式可能更快,因为它更能利用现代操作系统底层机制,避免不必要拷贝和上下文切换。
8、写正则表达式进行手机号匹配(*2)
# 号码规则:
1、第 1 位: 1
2、第 2 位: 3~9
3、第 3 到第 11 位只要是数字就行.
答案: /^[1]([3-9])[0-9]{
9}$/
(1) /^ - 表示文本开始;
(2) () - 子表达式的开始与结束;
(3) [] - 要匹配里面内容,[0-9]匹配数字范围为0/1/2/3/4/5/6/7/8/9;
(4) {
n} - 匹配n次,{
9}是匹配9次;
(5) ^ - 字符串开始,\^ - 匹配 ^ 字符本身; $ - 字符串结束。
三、参考
1、Java语法----Java中equals和==的区别
2、你真的懂 == 和 equals 的区别吗?
3、为什么重写了equals()也要重写hashCode()
4、重写equals方法后重写hashCode方法的必要性
5、手机号段正则表达式 (2019-01 最新)
6、正则表达式 - 语法
7、【疑惑整理】【Java】深入浅出HashMap+面试整理