文章目录
- 1.ArrayList和LinkedList区别
- 2.HashMap和HashTable区别
- 3.线程的创建方式
- 4.Java中异常处理
- 5.Java序列化中某些字段不想进行序列化?
- 6.Java序列化
- 7.静态方法和实例方法
- 8.List、Set、Map三者区别
- 9.ArrayList和Vector区别
- 10.HashMap和HashSet区别
1.ArrayList和LinkedList区别
- 是否保证线程安全:ArrayList和LinkedList都是不同步的,也就是说不保证线程安全。
- 底层数据结构:ArrayList底层使用的是Object数组;LinkedList底层使用的是双向链表。
- 插入和删除是否受元素位置影响:ArrayList采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。比如:执行add(e)方法的时候,ArrayList会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置i进行插入或删除操作add(i,e),时间复杂度就为O(n-i)。因为在进行上述操作时集合中第i和第i个元素之后的(n-i)个元素都要执行向后位/向前移一位操作。LinkedList采用链表存储,所以对于add(e)方法插入删除元素复杂度不受元素位置的影响,近似O(1),如果要在指定位置i插入删除元素的话add(i,e),时间复杂度近似为O(n),因为需要先移动到指定位置再插入。
- 是否支持快速随机访问:LinkedList不支持高效的随机元素访问,而ArrayList支持。快速随机访问就是通过元素的序号快速获取元素对象。
- 内存空间占用:ArrayList的空间浪费主要体现在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它每一个元素都需要消耗比ArrayList更多的空间,因为需要存放直接后继和直接前驱以及数据。
2.HashMap和HashTable区别
线程安全性不同
HashMap是线程不安全的,HashTable是线程安全的,其中的方法都通过Synchronized修饰,在多线程并发的情况下,可以直接使用HashTable,但是适用HashMap时必须自己增加同步处理。
是否提供contains方法
HashMap只有containsValue
和containsKey
方法;HashTable有contains
、containsKey
、containsValue
三个方法,其中contains
和containsValue
方法功能相同。
key与value是否允许null值
HashTable中,key和value都不允许出现null值。HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。
数组初始化和扩容机制
HashTable在不指定容量的情况下默认容量为11,而HashMap为16,HashTable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
HashTable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。
3.线程的创建方式
- 继承Thread类创建线程
- 实现Runnable接口创建线程
- 使用Callable和Future创建线程
- 使用线程池创建线程
4.Java中异常处理
在Java中,所有异常都有一个共同的祖先java.lang包中的Throwable类。Throwable有两个重要的子类:Exception(异常)和Error(错误),二者都是Java异常处理的重要子类,各自包含大量子类。
Error(错误):程序无法处理的错误,表示允许应用程序中较严重的问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时JVM出现的问题。
Exception(异常):程序本身可以处理的异常。Exception类有一个重要的子类RuntimeException。RuntimeException异常由Java虚拟机抛出。NullPointerException(要访问的变量没有引用任何对象时,抛出该异常)、ArithmeticException(算术运算异常,一个整数除以0时,抛出异常)和ArrayIndexOutOfBoundsException(下标越界异常)。
Throwable类常用的方法:
public string getMessage()
:返回异常发生时的简要描述。public string toString()
:返回异常发生时的详细信息。public string getLocalizedMessage()
:返回异常对象的本地化信息。使用Throwable的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与getMessage()返回的结果相同。public void printStackTrace()
:在控制台打印Throwable对象封装的异常信息。
异常处理总结:
- try块:用于捕获异常。其后可以接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
- catch块:用于处理try捕获到的异常。
- finally块:无论是否捕获或处理异常,finally块里的语句都会被执行。当try块或catch块中遇到return语句,finally语句块将在方法返回之前被执行。
在以下四种特殊情况,finally块不会被执行
- finally语句第一行发生异常。
- 在前面的代码中用了System.exit(int)已退出程序。exit是代餐函数;若该语句在异常语句之后,finally会执行。
- 程序所在的线程死亡。
- 关闭CPU。
5.Java序列化中某些字段不想进行序列化?
对于不想进行序列化的变量,使用transient
关键字修饰。
transient
关键字的作用:阻止实例中那些用此关键字修饰的变量序列化;当对象被反序列化时,被transient修饰的变量值不会被持久化和恢复。transient
只能修饰变量,不能修饰类和方法。
6.Java序列化
- 序列化是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。
- 序列化实现:将需要序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出,要恢复的话则用输入流。
7.静态方法和实例方法
- 在外部调用静态方法时,可以使用"类名.方法名",也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式,也就是说,调用静态方法可以无需创建对象。
- 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法。实例方法则无此限制。
8.List、Set、Map三者区别
- List(对付顺序的好帮手):List接口存储一组不唯一(可以有多个元素引用的对象),有序的对象。
- Set(注重独一无二的性质):不允许重复的集合,不会有多个元素引用相同的对象。
- Map(用key来搜索的专家):使用键值对存储。Map会维护与Key有关联的值。两个Key可以引用相同的对象,但Key不能重复,典型的Key是String类型,但也可以是任何对象。
9.ArrayList和Vector区别
Vector
类的所有方法都是同步的,可以由两个线程安全地访问一个Vector
对象,但是一个线程访问Vector的话代码要在同步操作上耗费大量时间。
ArrayList
不是同步的,所以不需要保证线程安全时建议使用ArrayList
。
10.HashMap和HashSet区别
HashSet底层就是基于HashMap实现的。(除了clone()、writeObject()、readObject()是HashSet自己实现的,其他的方法都是直接调用HashMap中的方法)。
HashMap | HashSet |
---|---|
实现Map接口 | 实现Set接口 |
存储键值对 | 仅存储对象 |
调用put()向map中添加元素 | 调用add()方法向Set中添加元素 |
HashMap使用键(Key)计算HashCode | HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性 |