1、HashMap和HashTable区别
HashMap是HashTable的轻量实现(非线程安全),他们都实现的Map接口,主要区别在于:线程安全,同步,性能
- HashTable继承Dictionary,HashMap继承的是java2出现的Map接口;
- HashMap允许将null作为key或value,hashtable不允许;
- HashMap是非同步的,HashTable是同步的(synchronized),所以HashMap线程不安全,而HashTable是线程安全的,多个线程可以共享一个HashTbale而不需要为自己的方法实现同步。Java5提供了ConcurrentMap,用来替代HashTable,比HashTable扩展性好;
- 由于HashMap是非线程安全的,所以单一线程访问,HashMap性能要高于HashTable;
- HashMap的迭代器(Iterator)是fail-fast迭代器,HashTable的enumerator迭代器不是fail-fast的。
- HashMap把HashTable的contains方法去掉了,换成了containsValue和containsKey
- HashTable中数组默认大小是11,扩容方法是old*2+1;HashMap默认大小是16,扩容每次为2的指数大小
2、Object的hashcode方法,equals方法,常用的地方
3、HashMap的原理应用场景
简单的说,HashMap是由数组和链表组成的,主体是数组,链表的作用主要是为了解决哈希冲突而存在的。在JDK1.8之后,链表长度超过8之后,会转换为红黑树。HashMap的默认容量为16,阈值为0.75,总容量超过0.75时,会进行2倍扩容。
4、JDK中有哪些线程池
Java中通过Executors提供四种线程池:
- newCachedTheadPool: 创建一个可缓存的线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无回收,则创建线程。此线程池不会对线程池大小做限制,线程池大小完全依赖系统能够创建的最大线程大小。
- newFixedThreadPool: 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
- newScheduleThreadPool: 创建一个定长线程池,支持定时及周期性任务执行
- newSingleThreadExecutor: 创建一个单线程化的线程池,他只会用唯一的工作线程来执行任务,保证所有任务按照先定顺序(FIFO,LIFO优先级执行)
5、TCP/UDP区别
相同点: 都处于OSI七层模型的网络层,都是传输层协议,都能保护网络层的传输,双方通信都需要开放端口。
| TCP | UDP | |
|---|---|---|
| 1 | Transmission Control Protocol 传输控制协议 | User Data Protocol 用户数据报协议 |
| 2 | TCP的传输是可靠传输 | UDP的传输是不可靠传输 |
| 3 | TCP是基于连接的协议,在正式收发数据前,必须和对方建立可靠的连接 | UDP是和TCP相对应的协议,他是面向非连接的协议,他不与对方建立连接,而是直接把数据包发送出去 |
| 4 | TCP是一种可靠的通信服务,负载相对而言比较大,TCP用套接字(socket)或者端口进行通信 | UDP是一种不可靠的网络服务,负载相对较小 |
| 5 | TCP和UP的结构不同,TCP包括序号、确认信号、数据偏移、控制标志(通常URG、ACK、PSH、RST、SYN、FIN)、窗口、检验和、紧急指针、选项等信息 | UDP包含长度和检验和信息 |
| 6 | TCP提供超时重发,丢弃重复数据,检验数据,流量控制等,保证数据从一端传到另一端 | UDP不提供可靠性,他只是把应用程序传给IP层的数据发送出去,但是不能保证他们到达目的端 |
| 7 | TCP发送数据包前会在通信双方间建立三次握手,确保双方准备好,在传输数据包期间,TCP会根据链路中数据流量的大小来调节传送的速率,传输时如果发现有丢包,会有严格的重传机制,故而传输速度很慢 | UDP在传输数据报前不用在客户端和服务器之间建立连接,且没有超时重发机制,故而传输速度很快 |
| 8 | TCP支持全双工和并发的TCP连接,提供确认、重传、拥塞控制 | UDP适用于对系统性能要求高于数据完整性的要求,需要简短快捷的数据交换、需要多播和广播的应用环境 |
6、查找一个数组的中位数
7、反射的机制,说说反射的用途和实现,反射是不是很慢,我们在项目中是否应该避免使用反射。
8、Object类中的方法
9、对象比较是否相等
10、toString方法的常用地方,为什么要重写该方法
11、HashMap put方法怎么判断是否是重复方法
12、Set和List的区别
13、ArrayList和LinkedList的区别,List和Map的区别, ArrayList和Vector的区别
- ArrayList和LinkedList区别:
- ArrayList内部是基于数组实现的,因此对于随机访问快,新增删除慢
- LinkedList内部是基于链表实现的,因此新增删除快,随机访问慢。
- List和Map的区别:
- List是存储单列数据的集合,存储的数据都是有序并且是可以重复的
- Map是存储双列数据的集合,通过键值对存储数据,存储的数据是无序的,Key值不能重复,value值是可以重复的。
- ArrayList和Vector的区别:
- ArrayList是不同步的,也就是不是线程安全的类
- Vector是同步的,线程安全
14、TreeSet对存入的数据有什么要求吗?
15、HashSet是不是线程安全的
16、Java中有哪些线程安全的Map
17、CocurrentHashMap是怎么做到线程安全的
18、如何保证线程安全问题
19、volatile原子性问题?为什么i++不支持原子性
20、CAS操作
21、lock和synchronized区别
22、公平锁和非公平锁
23、Java读写锁,读写锁解决的问题
24、线程池的原理,为什么要创建线程池?创建线程池的方式?
使用线程池的好处: 线程可以重复利用,减少创建、销毁线程带来的系统资源的开销,提高性能
25、线程的生命周期,什么时候会出现僵死进程?
26、创建线程池有哪几个核心参数,如何合理配置线程池的大小?
27、volatile、ThreadLocal的使用场景和原理
28、Synchronized、Volatile区别,Synchronized锁粒度,模拟死锁场景、原子性与可见性。
29、JVM内存模型、GC机制和原理
30、GC分那两种,Minor GC和Full GC有什么区别,什么情况下会触发Full GC,分别采用什么算法。
31、JVM里有几种classloader,为什么会有多种。
JVM里有三种类加载器:BootStrap Loader 负责加载系统类,ExtClassLoader负责加载扩展类,AppClassLoader负责加载应用类。
他们的分工不一样,各自负责不同的区域,另外也是为了实现委托模型。
当执行java *.class的时候,java会帮助我们找到jre,接着找到jre内部的jvm.dll,这个才是真正的java虚拟机,最后加载动态库,激活java虚拟机。虚拟机激活后,会先做一些初始化的动作,比如读取系统参数,一旦初始化动作完成,就会产生第一个类加载器-Bootstrap Loader,Bootstrap Loader是由C++编写的,该Loader所做的初始化工作中,除了一些基本的初始化动作之外,最重要的就是加载Launcher.java中的ExtClassLoader,并设定其parent为null,但其实其父加载器就是Bootstrap Loader。然后Bootstrap Loader在要求加载Launcher.java中的AppClassLoader,并设定其Parent为ExtClassLoader。需要注意的是Launcher$ExtClassLoader和Launcher$AppClassLoader都是由BootstrapLoader加载的,所以Parent和由哪个类加载没有关系。
32、什么是双亲委派机制,介绍双亲委派的运作过程和好处
双亲委派模式的工作原理是,如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器。如果父加载器可以完成加载任务,就成功返回;如果如果父加载器无法完成加载任务,子加载器才会尝试自己去加载,这就是双亲委托模型。
采用双亲委派模型的害处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关系可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。其次是考虑到安全因素,java核心api中定义类型不会随意被替换,比如通过网络传递一个java.lang.Integer的类,通过双亲委派模型传递到父类加载器,而启动类加载器在核心Java API中已经发现了这个类,所以并不会加载网络传递过来的Java.lang.Integer,而是直接返回已经加载过的Integer,这样便可以防止核心API被人随意篡改。
33、什么情况下需要破坏双亲委派机制
1、基础类调用用户代码
双亲委派很好地解决了各个类加载器的基础类的同一问题(越基础的类由越上层的加载器进行加载),基础类之所以称为“基础”,是因为它们总是作为被用户代码调用的API,但世事往往没有绝对的完美。如果基础类又要调用回用户的代码,那该么办?一个典型的例子就是JNDI服务,JNDI服务现在已经是Java的标准服务。JNDI的目的是对资源进行集中管理和查找,但是它需要调用有独立厂商实现并部署在应用程序ClassPath下的JNDI接口提供者(如mysql连接驱动、sql连接驱动)的代码,但是启动类加载器不识别这些代码。
为了解决这个问题,Java设计团队引入了一个不太优雅的设计:线程上下文类加载器(Thread Context ClassLoader)。有了线程上下文类加载器,JNDI就可以使用它去加载所需要的SPI代码,也就是父类加载器请求子类加载器去完成类加载的动作,这种行为实际上打破了双薪委派模型层次结构来逆向使用类加载器。JAVA中所有涉及SPI的加载动作基本上都是采用这种方式,例如JNDI、JDBC、JCE、JAXB等。
2、OSGi模块化热部署
OSGI实现模块化热部署的关键是它自定义的类加载器机制的实现,每一个程序模块都有一个自己的类加载器,当需要等换一个模块时,就把模块连同类加载器一起换掉以实现代码的热替换。
34、常见的JVM调优方法有哪些?可以调整哪个参数,调成什么值。
35、红黑树的实现原理和应用场景
36、NIO是什么,适用于何种场景
37、八种基本数据类型的大小,以及他们的封装类
byte、short、int、char、float、double、long、boolean
1、2、4、2、4、8、8、1
Byte、Short、Integer、Character、Float、Double、Long、Boolean
38、引用数据类型
类、接口类型、数组类型、枚举类型、注解类型
基本数据类型在创建时,在栈上给其划分一块内存,将数值直接存储在栈上。
引用数据类型在创建时,首先在栈上给其引用分配一块内存,而对象的具体信息都存储在堆内存中,然后由栈上的引用指向堆中对象的地址。
39、switch能否用string做参数
jdk7之前只能用byte、short、char、int这几个基本数据类型和其对应的封装类型。switch后面的括号内只能放置int类型的数据,由于byte、short、char都可以自动转为int类型,所以可以支持。
jdk7之后整形、枚举类型、字符串都可以,但是jdk7并没有新的指令处理switch string,而是通过string.hashcode,将string转换为int进行判断。
40、equals和==的区别
1、使用==比较原生类型如 boolean、int、char等,使用equals比较对象
2、==是判断两个变量或者实例是不是指向同一个内存空间。equals是判断两个变量或者实例所指向的内存空间的值是不是相同
3、==是指对内存地址进行比较,equals是对字符串的内容进行比较
4、==是指引用是否相同,equals指的是值是否相同。