A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

Java常见面试题目考点一

1. Hashmap的工作原理?
HashMap底层是数组+链表(以数组存储元素,如有hash相同的元素,在数组结构中,创建链表结构,再把hash相同的元素放到链表的下一个节点),基于hashing (散列法(Hashing)或哈希法是一种将字符组成的字符串转换为固定长度(一般是更短长度)的数值或索引值的方法) 原理,通过put()和get()方法来储存和获取对象。当我们将键值对传递给put()方法的时候,调用键对象的hashCode()方法来计算哈希值,然后找到bucket(桶)位置来储存值对象。当我们要获取对象的时候,通过键对象的equal()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞的问题,当发生碰撞了,对象就会储存在链表的下一个节点中。HashMap在每个链表节点中储存键值对对象。
2.HashMap和HashTable的区别?
主要区别有:线程安全性,同步(synchronization),以及速度
① HashMap是非同步的,而HashTable是同步的,意味着HashTable是线程安全的,多个线程可以共享一个HashTable,没有正确同步的话,多个线程不能共享HashMap.
② HashMap可以接收null的键值对(keyvalue都可以为null),HashTable则不行.
③ HashMap的迭代器(Iterator)是fail-fast迭代器.当有其他线程改变了HashMap的结构(例如增加或者移除元素),将会抛出异常.
集合中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件
④ HashTable是线程安全的,同时也是同步的,所以在单线程下比HashMap要慢。另外HashMap不能保证随着时间的推移Map中的元素次序是不变的。要保持元素顺序不变,除非是LinkedHashMap。
3.能否让HashMap同步?
HashMap可以通过下面的语句进行同步:
Map m = Collections.synchronizeMap(hashMap);
3.1 HashMap的扩容
默认的负载因子大小为0.75,也就是说,当一个map填满了75%的bucket时候,和其它集合类(如ArrayList等)一样,将会创建原来HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程叫作rehashing,因为它调用hash方法找到新的bucket位置。当多线程的情况下,可能产生条件竞争(race condition)。
3.2 hashMap在1.71.8中有什么变化?
JDK1.7中:使用一个Entry数组来存储数据,用key的hashcode取模来决定key会被放到数组里的位置,通常hashMap查询的时间复杂度是O(N).
JDK1.8中:使用一个Node数组来存储数据,但这个Node可能是链表结构,也可能是红黑树结构,链表的长度如果>8,就会变成红黑树,即数组+链表+红黑树.
1.7里是每次扩容都去计算元素的hash值,从而改变该元素在数组中的位置容量,容量变了,位置自然就要改变。1.8中使用的是2次幂的扩展(指长度扩为原来2倍),所以,元素的位置要么是在原位置,要么是在原位置再移动2次幂的位置。
4.什么是HashSet?
HashSet实现了Set接口,他不允许集合中有重复的值,当我们将对象存储在HashSet之前,要先确保对象重写equals()方法和hashCode()方法,这样才能比较对象的值是否相等,以确保set中没有储存相等的对象。
5HashSet和HashMap的区别
*HashMap*
*HashSet*
HashMap实现了Map接口
HashSet实现了Set接口
HashMap储存键值对
HashSet仅仅存储对象
使用put()方法将元素放入map中
使用add()方法将元素放入set中
HashMap中使用键对象来计算hashcode值
HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false
HashMap比较快,因为是使用唯一的键来获取对象
HashSet较HashMap来说比较慢
6. 抽象类(abstract class)和接口(interface)有什么异同?
①成员区别:抽象类成员可以是变量或常量,拥有构造方法,可以有抽象方法和非抽象方法,接口的成员变量只能是常量,没有构造方法,都是抽象方法
②关系区别:抽象类子类使用extends关键字来继承,只能单继承或者多重继承;接口子类使用implements来实现,可以多实现.
③设计理念:抽象类的方法可以有public,protected和defalut修饰符,接口默认修饰符只有public。抽象类体现的是“is a”的关系,体现在共性功能方面,接口体现的是“like a”的关系,体现在扩展功能.
7.final、finally、finalize的区别?
final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,被其修饰的类不可继承。
finally:异常处理语句结构的一部分,表示总是执行。
finalize:Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
8.现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?
Thread.join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程,比如说在线程T2中调用了线程T1的join方法,直到线程T1执行完毕后,才会继续执行线程T2.
t.join(); //调用join方法,等待线程t执行完毕
t.join(1000); //等待 t 线程,等待时间是1000毫秒。
8.1多线程的创建方式
①继承 Thread类:但Thread本质上也是实现了Runnable 接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过 Thread 类的 start()实例方法。
②实现Runnable接口的方式实现多线程,并且实例化Thread,传入自己的Thread实例,调用run( )方法
③实现Callable接口, 可返回值的任务必须实现Callable接口。执Callable任务后,可以获取一个 Future 的对象,在该对象上调用 get 就可以获取到 Callable 任务返回的 Object 了,再结合线程池接ExecutorService就可以实现传说中有返回结果的多线程了。
9. java中wait和sleep方法的不同?
最大的不同是在等待时wait会释放锁,而sleep一直持有锁。wait通常被用于线程间交互,sleep通常被用于暂停执行。
Java的多线程锁是挂在对象上的,并不是在方法上的。即每个对象都有一个锁. Java中获取锁的单位是线程。当线程A获取了对象B的锁,也就是对象B的持有标记上写的是线程A的唯一标识,在需要同步的情况下的话,只有线程A能访问对象B。
9.1 synchronized和volatile关键字的作用?
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
①保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说也是立即可见的。
②禁止进行指令重排序
synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
①volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的  
②volatile仅能实现变量的修改可见性,并不能保证原子性;synchronized则可以保证变量的修改可见性和原子性  
③volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。  
④volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化  
10. 请叙述一下您对线程池的理解.
① 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
②提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
③提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
10.1 常用的线程池有哪些,特点以及方法
①newSingleThreadExecutor:创建一个单线程的线程池,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
②newFixedThreadPool:创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。
③newCachedThreadPool:创建一个可缓存的线程池,此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
④newScheduledThreadPool:创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。
10.2 线程的可用状态及生命周期
就绪(Runnable):线程准备运行,不一定立马就能开始执行。
运行中(Running):进程正在执行线程的代码。
等待中(Waiting):线程处于阻塞的状态,等待外部的处理结束。
睡眠中(Sleeping):线程被强制睡眠。
⑤I/O阻塞(BlockedonI/O):等待I/O操作完成。
同步阻塞(BlockedonSynchronization):等待获取锁。
死亡(Dead):线程完成了执行。

1 个回复

倒序浏览
奈斯,加油加油
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马