- 获取键盘输入的常用方法
方法一:通过Scanner
Scanner input = new Scanner(System.in);
String s = input.nextLine();
input.close();
方法二:通过BufferedReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();
- 接口和抽象类的区别是什么?
(1) 接口不能有方法的实现,默认是public;抽象类可以有非抽象方法。
(2) 接口的实例变量默认是final,而抽象类不一定。
(3) 一个类可实现多个接口,但最多只能实现有一个抽象类。
(4) 一个类要实现接口必须实现其所有方法,而抽象类不一定。 - ArrayList和LinkedList:
是否保证线程安全: ArrayList和LinkedList都是不同步的,都不保证线程安全。
底层数据结构:ArrayList底层是Object数组,LinkedList底层使用双向链表数据结构。
插入元素时:ArrayList插入元素时默认插入最后一个,如果指定位置i的话复杂度为O(n-i);LinkedList插入元素不受位置的影响,无论再什么位置插入复杂度都为O(1)。
快速访问:ArrayList访问任意位置元素通过元素位置序号(通过get(int index)方法),LinkedList不支持高校的随机元素访问。 - Vector
Vector类所有的方法都是同步的,也就是线程安全的。可以由多个线程安全的访问一个Vector对象。但是单个线程访问Vector对象时需要消耗大量时间进行同步操作。
ArrayList是不同步的,因此在不保证线程安全的环境下使用ArrayList。 - HashMap的底层实现
HashMap实际上由数组和链表构成。HashMap通过Key的hashCode()经过哈希算法处理后得到hash值,然后通过(n-1)&hash判断当前元素存放的位置,如果当前位置存在元素的话,就判断存在元素的hash值以及key是否相同,如果相同就直接覆盖,不相同就采用拉链法解决冲突。
拉链法:如果遇到哈希冲突,在数组的这一格创建一个链表,用于存放冲突的值。在jdk1.8以后,若链表的长度大于阈值(默认为8),就将链表转化为红黑树。 - HashSet的底层
HashSet实现的是set接口,由哈希表支持。不保证迭代顺序,允许使用null元素。
HashSet是将相应的内容存储在一个HashMap的key中,然后再去读取。为了保证HasnSet的数据一致性,这里将HashSet存放的元素作为HashMap唯一的key变量,value部分用一个PRESENT对象储存,源码为:
private static final Object PRESENT = new Object();
- HashMap和HashTable的区别
线程是否安全:HashTable是线程安全的,HasnMap线程不安全。(HashTable的方法都是经过synchronized修饰,如果想保证线程安全可以使用ConcurrentHashMap)
效率:HashMap比Hashable效率高,并且HashTable基本被淘汰。
Null key 和Null value:HashMap中只能有一个Null key,但是可以有多个Null value。HashTable中不能有Null key,否则会抛出NullPointerException。
初始容量和每次扩容大小:HashTable的默认容量为11,之后扩容的容量变为原来的2n+1。HashMap默认初始值为16,之后每次扩容的容量变为2倍;如果给定容量,HashTable会使用给定的容量,而HashMap会将其扩充为2的幂次方大小。
底层数据结构:HashMap底层是数组和链表,在1.8以后将链表转化为红黑树。 - HashMap为什么使用2的幂次方作为长度?
因为HashMap为了防止哈希冲突,尽可能把数据均匀分布。Hash值大约有40亿的映射空间,只要哈希函数映射的比较松散,一般很难出现碰撞。但40亿的长度内存是放不下的,因此要对数组的长度进行取模运算,得到的余数才能作为对于数组的下标。这个下表计算的方法是(n-1)& Hash。