操作系统中 heap 和 stack 的区别
什么是基于注解的切面实现
什么是 对象/关系 映射集成模块
什么是 Java 的反射机制
什么是 ACID
BS与CS的联系与区别
Cookie 和 Session的区别
fail-fast 与 fail-safe 机制有什么区别
get 和 post请求的区别
Interface 与 abstract 类的区别
IOC的优点是什么
IO 和 NIO的区别,NIO优点
Java 8 / Java 7 为我们提供了什么新功能
什么是竞态条件? 举个例子说明。
JRE、JDK、JVM 及 JIT 之间有什么不同
MVC的各个部分都有那些技术来实现?如何实现?
RPC 通信和 RMI 区别
什么是 Web Service(Web服务)
JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。
WEB容器主要有哪些功能? 并请列出一些常见的WEB容器名字。
一个”.java”源文件中是否可以包含多个类(不是内部类)?有什么限制
简单说说你了解的类加载器。是否实现过类加载器
解释一下什么叫AOP(面向切面编程)
请简述 Servlet 的生命周期及其相关的方法
请简述一下 Ajax 的原理及实现步骤
简单描述Struts的主要功能
什么是 N 层架构
什么是CORBA?用途是什么
什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”
什么是正则表达式?用途是什么?哪个包使用正则表达式来实现模式匹配
什么是懒加载(Lazy Loading)
什么是尾递归,为什么需要尾递归
什么是控制反转(Inversion of Control)与依赖注入(Dependency Injection)
关键字
finalize
什么是finalize()方法
finalize()方法什么时候被调用
析构函数(finalization)的目的是什么
final 和 finalize 的区别
final
final关键字有哪些用法
final 与 static 关键字可以用于哪里?它们的作用是什么
final, finally, finalize的区别
final、finalize 和 finally 的不同之处?
能否在运行时向 static final 类型的赋值
使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变
使用final关键字修饰一个引用变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。
一个类被声明为final类型,表示了什么意思
认为该类已经达到完美,完全没有必要再去修改它,用final关键字。
不希望该类被继承,用final关键字修饰。
throws, throw, try, catch, finally分别代表什么意义
Java 有几种修饰符?分别用来修饰什么
volatile
volatile 修饰符的有过什么实践
答:1,线程1执行doWork()的过程中,可能有另外的线程2调用了shutdown,所以boolean变量必须是volatile。
2,独立观察,定期 “发布” 观察结果供程序内部使用。【例如】假设有一种环境传感器能够感觉环境温度。一个后台线程可能会每隔几秒读取一次该传感器,并更新包含当前文档的 volatile 变量。然后,其他线程可以读取这个变量,从而随时能够看到最新的温度值。
3,线程安全的计数器,使用 synchronized 确保增量操作是原子的,并使用 volatile 保证当前结果的可见性。如果更新不频繁的话,该方法可实现更好的性能,因为读路径的开销仅仅涉及 volatile 读操作,这通常要优于一个无竞争的锁获取的开销。
4,单例双检锁
总结一下,可以分为5个:作为状态位发布;一次性安全发布;独立观察;volatile bean模式;开销较低的读写锁策略。
volatile 变量是什么?volatile 变量和 atomic 变量有什么不同
答:1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2)禁止进行指令重排序。
//线程1
boolean stop = false;
while(!stop){
doSomething();
}
//线程2
stop = true;
这个代码能够把线程中断,但是也有可能会导致无法中断线程。每个线程在运行过程中都有自己的工作内存,那么线程1在运行的时候,会将stop变量的值拷贝一份放在自己的工作内存当中。那么当线程2更改了stop变量的值之后,但是还没来得及写入主存当中,线程2转去做其他事情了,那么线程1由于不知道线程2对stop变量的更改,因此还会一直循环下去。但是用volatile修饰之后就变得不一样了:第一:使用volatile关键字会强制将修改的值立即写入主存;第二:使用volatile关键字的话,当线程2进行修改时,会导致线程1的工作内存中缓存变量stop的缓存行无效(反映到硬件层的话,就是CPU的L1或者L2缓存中对应的缓存行无效);第三:由于线程1的工作内存中缓存变量stop的缓存行无效,所以线程1再次读取变量stop的值时会去主存读取。那么线程1读取到的就是最新的正确的值。
happens-before规则中的volatile变量规则,但是要注意,线程1对变量进行读取操作之后,被阻塞了的话,并没有对inc值进行修改。然后虽然volatile能保证线程2对变量inc的值读取是从内存中读取的,但是线程1没有进行修改,所以线程2根本就不会看到修改的值。自增操作是不具备原子性的,它包括读取变量的原始值、进行加1操作、写入工作内存。
volatile 类型变量提供什么保证?能使得一个非原子操作变成原子操作吗
答:volatile 变量提供顺序和可见性保证,例如,JVM 或者 JIT为了获得更好的性能会对语句重排序,但是 volatile 类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。 volatile 提供 happens-before 的保证,确保一个线程的修改能对其他线程是可见的。
某些情况下,volatile 还能提供原子性,如读 64 位数据类型,像 long 和 double 都不是原子的,但 volatile 类型的 double 和 long 就是原子的。
volatile修饰的变量如果是对象或数组之类的,其含义是对象获数组的地址具有可见性,但是数组或对象内部的成员改变不具备可见性:
能创建 volatile 数组吗?
答: volatile修饰的变量如果是对象或数组之类的,其含义是对象获数组的地址具有可见性,但是数组或对象内部的成员改变不具备可见性
:
transient变量有什么特点
答:
我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。
然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
super什么时候使用
答:子类的构造函数中不是必须使用super,在构造函数中,如果第一行没有写super(),编译器会自动插入.但是如果父类没有不带参数的构造函数,或这个函数被私有化了(用private修饰).此时你必须加入对父类的实例化构造.而this就没有这个要求,因为它本身就进行实例化的构造.
如果父类的构造函数是无参的,那子类构造函数会在第一行默认调用super().
下面这种情况是必须调用super()的:
1 public class Father {
2 public String name;
3 public Father(String name) {
4 this.name = name;
5 }
6 }
7
8 class Son extends Father{
9 public Son(String name) {
10 super(name);
11 }
12 //必须调用,否则他会默认调用父类的无参构造函数,而父类的无参构造函数已经被有参的覆盖,所以找不到
public static void 写成 static public void会怎样
说明一下public static void main(String args[])这段声明里每个关键字的作用
请说出作用域public, private, protected, 以及不写时的区别
sizeof 是Java 的关键字吗
static
static class 与 non static class的区别
内部静态类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用。
非静态内部类能够访问外部类的静态和非静态成员。静态类不能访问外部类的非静态成员。他只能访问外部类的静态成员。
一个非静态内部类不能脱离外部类实体被创建,一个非静态内部类可以访问外部类的数据和方法,因为他就在外部类里面。
static 关键字是什么意思?Java中是否可以覆盖(override)一个private或者是static的方法
Static表示静态的意思,可用于修饰成员变量和成员函数,被静态修饰的成员函数只能访问静态成员,不可以访问非静态成员。静态是随着类的加载而加载的,因此可以直接用类进行访问。 重写是子类中的方法和子类继承的父类中的方法一样(函数名,参数,参数类型,反回值类型),但是子类中的访问权限要不低于父类中的访问权限。重写的前提是必须要继承,private修饰不支持继承,因此被私有的方法不可以被重写。静态方法形式上可以被重写,即子类中可以重写父类中静态的方法。但是实际上从内存的角度上静态方法不可以被重写。
静态类型有什么特点
答案:1、随着类的加载而加载
也就是说:静态会随着类的消失而消失,说明他的生命周期最长
2、优先于对象存在
3、被所有对象所共享
4、可以直接被类名调用
main() 方法为什么必须是静态的?能不能声明 main() 方法为非静态
答案:所有static成员都是在程序装载时初始化的,被分配在一块静态存储区域。这个区域的成员一旦被分配,就不再改变地址啦。直到程序结束才释放。main()就存储在这里。尽管包含main()的类还没有被实例化,但是main()方法已经可以使用啦。而且JVM将会自动调用这个方法。通过main()的调用,再实例化其他的对象,也包括自己所在的类。
是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用
静态变量在什么时候加载?编译期还是运行期?静态代码块加载的时机呢
答案:当类加载器将类加载到JVM中的时候就会创建静态变量,这跟对象是否创建无关。静态变量加载的时候就会分配内存空间。静态代码块的代码只会在类第一次初始化的时候执行一次。一个类可以有多个静态代码块,它并不是类的成员,也没有返回值,并且不能直接调用。静态代码块不能包含this或者super,它们通常被用初始化静态变量。
成员方法是否可以访问静态变量?为什么静态方法不能访问成员变量
答案:可以。static成员是在JVM的CLASSLOADER加载类的时候初始化的,而非static的成员是在创建对象,即new 操作的时候才初始化的;类加载的时候初始化static的成员,此时static 已经分配内存空间,所以可以访问;非static的成员还没有通过new创建对象而进行初始化,所以必然不可以访问。
简单点说:静态成员属于类,不需要生成对象就存在了.而非静态需要生成对象才产生,所以静态成员不能直接访问.
switch
switch 语句中的表达式可以是什么类型数据
switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上
while 循环和 do 循环有什么不同
操作符
&操作符和&&操作符有什么区别?
a = a + b 与 a += b 的区别?
逻辑操作符 (&,|,^)与条件操作符(&&,||)的区别
3*0.1 == 0.3 将会返回什么?true 还是 false?
float f=3.4; 是否正确?
short s1 = 1; s1 = s1 + 1;有什么错?
数据结构
基础类型(Primitives)
基础类型(Primitives)与封装类型(Wrappers)的区别在哪里
简述九种基本数据类型的大小,以及他们的封装类
int 和 Integer 哪个会占用更多的内存? int 和 Integer 有什么区别?parseInt()函数在什么时候使用到
float和double的默认值是多少
如何去小数四舍五入保留小数点后两位
char 型变量中能不能存贮一个中文汉字,为什么
类型转换
怎样将 bytes 转换为 long 类型
怎么将 byte 转换为 String
如何将数值型字符转换为数字
我们能将 int 强制转换为 byte 类型的变量吗?如果该值大于 byte 类型的范围,将会出现什么现象
能在不进行强制转换的情况下将一个 double 值赋值给 long 类型的变量吗
类型向下转换是什么
数组
如何权衡是使用无序的数组还是有序的数组 答案:
有序数组最大的好处:在于查找的时间复杂度是O(log n),而无序数组是O(n)。
有序数组的缺点是:插入操作的时间复杂度是O(n),因为值大的元素需要往后移动来给新元素腾位置。相反,无序数组的插入时间复杂度是常量O(1)。
怎么判断数组是 null 还是为空
怎么打印数组? 怎样打印数组中的重复元素
Array 和 ArrayList有什么区别?什么时候应该使用Array而不是ArrayList 答案:
Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
Array大小是固定的,ArrayList的大小是动态变化的。
ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。
数组和链表数据结构描述,各自的时间复杂度 答案:
1、存取方式上,数组可以顺序存取或者随机存取,而链表只能顺序存取;
2、存储位置上,数组逻辑上相邻的元素在物理存储位置上也相邻,而链表不一定;
3、存储空间上,链表由于带有指针域,存储密度不如数组大;
4、按序号查找时,数组可以随机访问,时间复杂度为O(1),而链表不支持随机访问,平均需要O(n);
5、按值查找时,若数组无序,数组和链表时间复杂度均为O(n),但是当数组有序时,可以采用折半查找将时间复杂度降为O(logn);
6、插入和删除时,数组平均需要移动n/2个元素,而链表只需修改指针即可;
7、空间分配方面:
数组在静态存储分配情形下,存储元素数量受限制,动态存储分配情形下,虽然存储空间可以扩充,但需要移动大量元素,导致操作效率降低,而且如果内存中没有更大块连续存储空间将导致分配失败;
链表存储的节点空间只在需要的时候申请分配,只要内存中有空间就可以分配,操作比较灵活高效;
数组有没有length()这个方法? String有没有length()这个方法
队列
队列和栈是什么,列出它们的区别 答案:
队列(Queue):是限定只能在表的一端进行插入和在另一端进行删除操作的线性表;
栈(Stack):是限定只能在表的一端进行插入和删除操作的线性表。
一、规则不同
1. 队列:先进先出(First In First Out)FIFO
2. 栈:先进后出(First In Last Out )FILO
二、对插入和删除操作的限定不同
1. 队列:只能在表的一端进行插入,并在表的另一端进行删除;
2. 栈:只能在表的一端插入和删除。
三、遍历数据速度不同
1. 队列:基于地址指针进行遍历,而且可以从头部或者尾部进行遍历,但不能同时遍历,无需开辟空间,因为在遍历的过程中不影响数据结构,所以遍历速度要快;
2. 栈:只能从顶部取数据,也就是说最先进入栈底的,需要遍历整个栈才能取出来,而且在遍历数据的同时需要为数据开辟临时空间,保持数据在遍历前的一致性。
BlockingQueue是什么 答案:
1.BlockingQueue队列和平常队列一样都可以用来作为存储数据的容器,但有时候在线程当中涉及到数据存储的时候就会出现问题,而BlockingQueue是空的话,如果一个线程要从BlockingQueue里取数据的时候,该线程将会被阻断,并进入等待状态,直到BlockingQueue里面有数据存入了后,就会唤醒线程进行数据的去除。若BlockingQueue是满的,如果一个线程要将数据存入BlockQueue,该线程将会被阻断,并进入等待状态,直到BlcokQueue里面的数据被取出有空间后,线程被唤醒后在将数据存入
2.BlockingQueue定义的常用方法详解:
1)add(anObject):把anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则报异常
2)offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false.
3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续.
4)poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null
5)take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止
3.BlockingQueue有四个具体的实现类,根据不同需求,选择不同的实现类
1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的.
2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的 BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含 的对象是以FIFO(先入先出)顺序排序的
3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.
4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的.
4.LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致 LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于 ArrayBlockingQueue.
简述 ConcurrentLinkedQueue LinkedBlockingQueue 的用处和不同之处。 答案:
1.由于LinkedBlockingQueue实现是线程安全的,实现了先进先出等特性,是作为生产者消费者的首选,LinkedBlockingQueue 可以指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。
2.LinkedBlockingQueue是一个线程安全的阻塞队列,它实现了BlockingQueue接口,BlockingQueue接口继承自java.util.Queue接口,并在这个接口的基础上增加了take和put方法,这两个方法正是队列操作的阻塞版本。
3.ConcurrentLinkedQueue是无阻塞的队列,可伸缩性比BlockingQueue高。ConcurrentLinkedQueue是Queue的一个安全实现.Queue中元素按FIFO原则进行排序.采用CAS操作,来保证元素的一致性。
4.两个都是线程安全的
ArrayList、Vector、LinkedList的存储性能和特性
String
StringBuffer
ByteBuffer 与 StringBuffer有什么区别
HashMap
HashMap的工作原理是什么 答案:
HashMap的底层是用hash数组和单向链表实现的 ,当调用put方法是,首先计算key的hashcode,定位到合适的数组索引,然后再在该索引上的单向链表进行循环遍历用equals比较key是否存在,如果存在则用新的value覆盖原值,如果没有则插入到链表linkedlist的头部。HashMap的两个重要属性是容量capacity和加载因子loadfactor,默认值分布为16和0.75,当容器中的元素个数大于 capacity*loadfactor时,容器会进行扩容resize 为2n,在初始化Hashmap时可以对着两个值进行修改,负载因子0.75被证明为是性能比较好的取值,通常不会修改,那么只有初始容量capacity会导致频繁的扩容行为,这是非常耗费资源的操作,所以,如果事先能估算出容器所要存储的元素数量,最好在初始化时修改默认容量capacity,以防止频繁的resize操作影响性能。
HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用LinkedList来解决碰撞问题,当发生碰撞了,对象将会储存在LinkedList的下一个节点中。 HashMap在每个LinkedList节点中储存键值对对象。
内部的数据结构是什么
HashMap 的 table的容量如何确定?loadFactor 是什么? 该容量如何变化?这种变化会带来什么问题? 答案:
HashMap使用的是懒加载,构造完HashMap对象后,只要不进行put 方法插入元素之前,HashMap并不会去初始化或者扩容table。这个问题可以跟踪一下HashMap的源码就知道了,根据输入的初始化容量(门槛?)的值(先了解HashMap中容量和负载因子的概念,其实这个和HashMap确定存储地址的算法有关),先判断是否大于最大容量,最大容量2的30次方,1<<30 =(1073741824),如果大于此数,初始化容量赋值为1<<30,如果小于此数,调用tableSizeFor方法 使用位运算将初始化容量修改为2的次方数,都是向大的方向运算,比如输入13,小于2的4次方,那面计算出来桶的初始容量就是16.
HashMap 实现的数据结构是什么?如何实现
HashMap 和 HashTable、ConcurrentHashMap 的区别
HashMap的遍历方式及效率
HashMap、LinkedMap、TreeMap的区别 Hashmap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
Hashtable与 HashMap类似,它继承自Dictionary类,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了 Hashtable在写入时会比较慢。
LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。
一般情况下,我们用的最多的是HashMap,HashMap里面存入的键值对在取出的时候是随机的,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。在Map 中插入、删除和定位元素,HashMap 是最好的选择。
LinkedHashMap 是HashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列,像连接池中可以应用。
TreeMap取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
如何决定选用HashMap还是TreeMap
如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办
HashMap 是线程安全的吗?并发下使用的 Map 是什么,它们内部原理分别是什么,比如存储方式、 hashcode、扩容、 默认容量等
HashSet
HashSet和TreeSet有什么区别 答案:1、TreeSet 是二叉树实现的,Treeset中的数据是自动排好序的,不允许放入null值。 TreeSet是SortedSet接口的唯一实现类,向TreeSet中加入的应该是同一个类的对象。
2、HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束。
3、HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例 。
HashSet 内部是如何工作的 答案:HashSet 的实现其实非常简单,它只是封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
WeakHashMap 是怎么工作的? 答案:WeakHashMap当系统内存不足时,垃圾收集器会自动的清除没有在任何其他地方被引用的键值对,因此可以作为简单缓存表的解决方案。而HashMap就没有上述功能。但是,如果WeakHashMap的key在系统内持有强引用,那么WeakHashMap就退化为了HashMap,所有的表项都不会被垃圾回收器回收。但是在WeakHashMap中会删除那些已经被GC的键值对在源码中是通过调用expungeStaleEntries函数来完成的,而这个函数只在WeakHashMap的put、get、size()等方法中才进行了调用。
Set
Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢?是用 == 还是 equals()? 它们有何区别? 答案:当使用HashSet时,hashCode方法就会得到调用,判断已经存储在集合中的对象的hash code值是否与增加的对象的hash code值一致:
- 如果不一致,直接加进去;
- 如果一致,再进行equals方法的比较,equals如果返回true,表示对象已经加进去了,就不会再增加新的对象;否则加进去。
TreeMap:TreeMap 是采用什么树实现的?TreeMap、HashMap、LindedHashMap的区别。TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素? 答案:TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。 三者区别参考文章:三者区别
TreeSet:一个已经构建好的 TreeSet,怎么完成倒排序。 答案:A:自然排序:要在自定义类中实现Comparerable<T>接口 ,并且重写compareTo方法
B:比较器排序:在自定义类中实现Comparetor<t>接口,重写compare方法
EnumSet 是什么 答案:Enumset是个虚类,我们只能通过它提供的静态方法来返回Enumset的实现类的实例。使用noneOf方法创建空的EnumSet,使用EnumSet.allOf方法创建一个拥有所有枚举类元素的EnumSet,使用EnumSet.of方法返回拥有部分元素的EnumSet,使用addAll方法,添加一个EnumSet中的所有元素到另外一个EnumSet,使用toArray方法,将EnumSet中的元素存放到数组中去
Hash算法
Hashcode 的作用
简述一致性 Hash 算法 答案:一致性hash算法提出了在动态变化的Cache环境中,判定哈希算法好坏的四个定义:
1、平衡性(Balance)
2、单调性(Monotonicity)
3、分散性(Spread)
4、负载(Load)
普通的哈希算法(也称硬哈希)采用简单取模的方式,将机器进行散列,这在cache环境不变的情况下能取得让人满意的结果,但是当cache环境动态变化时,这种静态取模的方式显然就不满足单调性的要求(当增加或减少一台机子时,几乎所有的存储内容都要被重新散列到别的缓冲区中)。
一致性哈希算法的基本实现原理是将机器节点和key值都按照一样的hash算法映射到一个0~232的圆环上。当有一个写入缓存的请求到来时,计算Key值k对应的哈希值Hash(k),如果该值正好对应之前某个机器节点的Hash值,则直接写入该机器节点,如果没有对应的机器节点,则顺时针查找下一个节点,进行写入,如果超过232还没找到对应节点,则从0开始查找(因为是环状结构)。
有没有可能 两个不相等的对象有相同的 hashcode?当两个对象 hashcode 相同怎么办?如何获取值对象 答案:有。 可以用equal比较值。
为什么在重写 equals 方法的时候需要重写 hashCode 方法?equals与 hashCode 的异同点在哪里
a.hashCode() 有什么用?与 a.equals(b) 有什么关系 答案:
1、hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;
2、如果两个对象相同,就是适用于equals(Java.lang.Object) 方法,那么这两个对象的hashCode一定要相同;
3、如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就会违反上面提到的第2点;
4、两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”。
再归纳一下就是hashCode是用于查找使用的,而equals是用于比较两个对象的是否相等的。
hashCode() 和 equals() 方法的重要性体现在什么地方
Object:Object有哪些公用方法?Object类hashcode,equals 设计原则? sun为什么这么设计?Object类的概述 答案:clone,getClass, toString, finalize, equal, hashCode,wait,notify, notifyAll Object类是所有Java类的祖先。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。
如何在父类中为子类自动完成所有的 hashcode 和 equals 实现?这么做有何优劣。
可以在 hashcode() 中使用随机数字吗?
答案:不可以。Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。
LinkedHashMap
LinkedHashMap 和 PriorityQueue 的区别是什么 答案:PriorityQueue 保证最高或者最低优先级的的元素总是在队列头部,但是 LinkedHashMap 维持的顺序是元素插入的顺序。当遍历一个 PriorityQueue 时,没有任何顺序保证,但是 LinkedHashMap 课保证遍历顺序是元素插入的顺序。
List
List, Set, Map三个接口,存取元素时各有什么特点
List, Set, Map 是否继承自 Collection 接口
遍历一个 List 有哪些不同的方式
LinkedList
LinkedList 是单向链表还是双向链表
LinkedList 与 ArrayList 有什么区别
描述下 Java 中集合(Collections),接口(Interfaces),实现(Implementations)的概念。LinkedList 与 ArrayList 的区别是什么?
插入数据时,ArrayList, LinkedList, Vector谁速度较快?
ArrayList
ArrayList 和 HashMap 的默认大小是多数 答案:hashMap为16,ArrayList为10.
但是ArrayList比较特殊,只是初始化了10个空的数组。详情参考点击打开链接
ArrayList 和 LinkedList 的区别,什么时候用 ArrayList?
ArrayList 和 Set 的区别?
ArrayList, LinkedList, Vector的区别
ArrayList是如何实现的,ArrayList 和 LinkedList 的区别
ArrayList如何实现扩容 答案:
在JDK1.7中,如果通过无参构造的话,初始数组容量为0,当真正对数组进行添加时,才真正分配容量。
每次按照1.5倍(位运算)的比率通过copeOf的方式扩容。
在JKD1.6中,如果通过无参构造的话,初始数组容量为10.每次通过copeOf的方式扩容后容量为原来的1.5倍加1.以上就是动态扩容的原理。
Array 和 ArrayList 有何区别?什么时候更适合用Array
说出ArraList,Vector, LinkedList的存储性能和特性
Map
Map, Set, List, Queue, Stack
Map 接口提供了哪些不同的集合视图 答案:
Map接口在Java集合中提供三个集合视图:
(1)Set keyset():返回map中包含的所有key的一个Set视图。集合是受map支持的,map的变化会在集合中反映出来,反之亦然。当一个迭代器正在 遍历一个集合时,若map被修改了(除迭代器自身的移除操作以外),迭代器的结果会变为未定义。
(2)Collection values():返回一个map中包含的所有value的一个Collection视图。这个collection受map支持的,map的变化会在 collection中反映出来,反之亦然。当一个迭代器正在遍历一个collection时,若map被修改了(除迭代器自身的移除操作以外),迭代器 的结果会变为未定义。
(3)Set<Map.Entry<K,V>> entrySet():返回一个map钟包含的所有映射的一个集合视图。这个集合受map支持的,map的变化会在collection中反映出来,反之 亦然。当一个迭代器正在遍历一个集合时,若map被修改了(除迭代器自身的移除操作,以及对迭代器返回的entry进行setValue外),迭代器的结 果会变为未定义。
以上集合都支持通过Iterator的Remove、Set.remove、removeAll、retainAll和clear操作进行元素 移除,从map中移除对应的映射。它不支持add和addAll操作。
为什么 Map 接口不继承 Collection 接口 答案:
尽管Map接口和它的实现也是集合框架的一部分,但Map不是集合,集合也不是Map。因此,Map继承Collection毫无意义,反之亦然。
如果Map继承Collection接口,那么元素去哪儿?Map包含key-value对,它提供抽取key或value列表集合的方法,但是它不适合“一组对象”规范。
Collections
介绍Java中的Collection FrameWork。集合类框架的基本接口有哪些
Collections类是什么?Collection 和 Collections的区别?Collection、Map的实现
集合类框架的最佳实践有哪些
为什么 Collection 不从 Cloneable 和 Serializable 接口继承
说出几点 Java 中使用 Collections 的最佳实践? 答案:
a)使用正确的集合类,例如,如果不需要同步列表,使用 ArrayList 而不是 Vector。
b)优先使用并发集合,而不是对集合进行同步。并发集合提供更好的可扩展性。
c)使用接口代表和访问集合,如使用List存储 ArrayList,使用 Map 存储 HashMap 等等。
d)使用迭代器来循环集合。
e)使用集合的时候使用泛型。
Collections 中 遗留类 (HashTable、Vector) 和 现有类的区别
什么是 B+树,B-树,列出实际的使用场景。
接口
Comparator 与 Comparable 接口是干什么的?列出它们的区别 答案:
1,Comparable
Comparable 定义在 Person类的内部:
public class Persion implements Comparable {..比较Person的大小..},
因为已经实现了比较器,那么我们的Person现在是一个可以比较大小的对象了,它的比较功能和String完全一样,可以随时随地的拿来
比较大小,因为Person现在自身就是有大小之分的。Collections.sort(personList)可以得到正确的结果。
2,Comparator
Comparator 是定义在Person的外部的, 此时我们的Person类的结构不需要有任何变化,如
public class Person{ String name; int age },
然后我们另外定义一个比较器:
public PersonComparator implements Comparator() {..比较Person的大小..},
在PersonComparator里面实现了怎么比较两个Person的大小. 所以,用这种方法,当我们要对一个 personList进行排序的时候,
我们除了了要传递personList过去, 还需要把PersonComparator传递过去,因为怎么比较Person的大小是在PersonComparator
里面实现的, 如:
Collections.sort( personList , new PersonComparator() ).