Java面试基础复习笔记(数据结构、关键字、方法)

数据结构:

1、List、ArrayList、LinkedList

List:元素是有序的(怎么存的就怎么取出来,顺序不会乱),元素可以重复(角标1上有个3,角标2上也可以有个3)因为该集合体系有索引。
ArrayList:底层的数据结构使用的是数组结构(数组长度是可变的百分之五十延长)(特点是查询很快,但增删较慢)线程不同步。

LinkedList:底层的数据结构是链表结构(特点是查询较慢,增删较快)。

2、HashMap
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。( 除了不同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。另外,HashMap是非线程安全的,也就是说在多线程的环境下,可能会存在问题,而Hashtable是线程安全的。
HashMap的本质仍然是数组,不过数组中存储的不是数据,而是一个链表的头节点。所以准确的说,其实现就是链表数组。HashMap中保存的是一个键值对,插入对象时必须提供一个键对象;查找对象时必须给定一个键对象(因此必须记住键)。键对象时不允许重复的,但是允许null空键的存在。 

HashMap插入对象时,根据给定的键key计算hashcode,然后再与数组长度进行求余运算得到数组下标。然后与该位置上的链表中已存储的键进行比较,对于已存在的键,则覆盖;对于不存在的键,则添加到链表尾。 

工作原理:
HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用LinkedList来解决碰撞问题,当发生碰撞了,对象将会储存在LinkedList的下一个节点中。 HashMap在每个LinkedList节点中储存键值对对象。 
当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同一个bucket位置的LinkedList中。键对象的equals()方法用来找到键值对。 
key对象相同则覆盖,hashcode相同则添加到链表尾。

3、HashMap与HashTable的区别
Hashtable 继承自 Dictionary 而 HashMap继承自AbstractMap。
HashTable:方法是同步的
 方法不允许value==null
 方法调用了key的hashCode方法,如果key==null,会抛出空指针异常
HashMap:方法是非同步的
 方法允许key==null
 方法并没有对value进行任何调用,所以允许为null

HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口。主要的区别有:线程安全性,同步(synchronization),以及速度。

4、HsahMap与HashSet的区别

*HashMap* *HashSet*
HashMap实现了Map接口 HashSet实现了Set接口
HashMap储存键值对 HashSet仅仅存储对象
使用put()方法将元素放入map中 使用add()方法将元素放入set中
HashMap中使用键对象来计算hashcode值 HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false
HashMap比较快,因为是使用唯一的键来获取对象 HashSet较HashMap来说比较慢

5、HashMap和TreeMap的区别

相同点:

HashMap非线程安全,TreeMap非线程安全。

都继承了AbstractMap。

不同点:

HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()(可以重写hashCode()和equals()),为了优化HashMap空间的使用,您可以调优初始容量和负载因子。

TreeMap:基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。

HashMap:适用于在Map中插入、删除和定位元素。

TreeMap:适用于按自然顺序或自定义顺序遍历键(key)。

HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap。

HashMap的结果是没有排序的。TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。HashMap里面存入的键值对在取出的时候是随机的,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。在Map中插入、删除和定位元素,HashMap是最好的选择。TreeMap取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。

6、树遍历
前序遍历、中序遍历、后序遍历、层序遍历,前、中、后为根节点遍历到的顺序,层序遍历每次遍历一层。
平衡:所有叶子都位于同一层,或至少是彼此相差不超过一个层。
完全:是平衡的,且底层的叶子都都位于树的左边。
堆:完全树,最小或最大。
二叉查找树:左孩子小于父节点,父节点小于或等于右孩子。

优先级队列:优先级队列,因为一般用二叉堆来实现,因此又称为堆。它的每一个父节点的值都比孩子节点大(或者小)。它的工作是查找或者删除优先队列中的最大值(或最小值)


基础:

1、说出final,finalize,finally的区别?

final是修饰符,被final修饰的类,就意味着不能再派生出新的子类,不能作为父类而被子类继承。因此一个类不能既被abstract声明,又被final声明。将变量或方法声明为final,可以保证他们在使用的过程中不被修改。被声明为final的变量必须在声明时给出变量的初始值,而在以后的引用中只能读取。被final声明的方法也同样只能使用,不能重载。

finalize是方法名。ava技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在object类中定义的,因此所有的类都继承了它。子类覆盖finalize()方法以整理系统资源或者被执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。

finally是在异常处理时提供finally块来执行任何清除操作。不管有没有异常被抛出、捕获,finally块都会被执行。try块中的内容是在无异常时执行到结束。catch块中的内容,是在try块内容发生catch所声明的异常时,跳转到catch块中执行。finally块则是无论异常是否发生,都会执行finally块的内容,所以在代码逻辑中有需要无论发生什么都必须执行的代码,就可以放在finally块中。

2、对于static关键字的理解。 
static修饰的域属于这个类,而不属于具体的某一个对象。 
static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。
被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。
静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。
static是不允许用来修饰局部变量。

3、重载和重写的区别? 子类可以重载父类的方法吗? 
重载:指的是同名的方法拥有不同的参数列表,而系统调用函数是能够根据参数列表选择正确的方法。 
重写:指的是是对父类方法的一种覆盖。 
子类不可以重载父类的方法,只能重写。

4、Object类常用方法

equals(),toString(),线程通信:wait(),notify(),notifyAll()。

5、常用的类,包,接口,常见的runtime exception
常用的类:BufferedReader、BufferedWriter、FileReader、FileWirter、String、Integer 、StringBuffer、Stack
常用的包:java.lang、java.awt、java.io、java.util、java.sql、javax.xml、java.NET
常用的接口: List、Map、Document、NodeList、Remote 

常见的异常:ClassCastException (强制转换异常)NullPointerException(空指针异常,使用Null时)ArrayIndexOutofBoundsException(数组越界)StringIndexOutBoundsException(指示索引或者为负或者超出字符串大小)IndexOutOfBoundsException(下标越界)NumberFormatException(数据格式异常,字符串->数字)FileNotFoundException(文件未找到异常)SQLException(操作数据库异常)IOException(I/O输入输出异常)

6、String、StringBuffer、StringBuilder

正常情况下执行效率:StringBuilder > StringBuffer > String(例外情况是String str = "abc"+"de",这种情况相当于String str = "abcde",所以快了不少)
Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。
而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。
String是字符串常量,StringBuffer和StringBuilder是字符串变量。
当字符串相加操作或者改动较少的情况下,建议使用 String str="hello"这种形式;
当字符串相加操作较多的情况下,建议使用StringBuilder;
如果采用了多线程,则使用StringBuffer。

7、泛型
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
泛型只在编译阶段有效。
定义一个泛型类:

public class Generic{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
    private T key;

    public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }

    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}
8、Java字节流、字符流
字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件。

详情见 https://blog.csdn.net/cynhafa/article/details/6882061

9、Java反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

你可能感兴趣的:(Java)