每日面试题

每日面试题

String为什么是final类?

为了安全性和效率。String类被final修饰不能被继承,所以不会被修改,可避免因为继承引起的安全隐患。String类在程序中出现的频率比较高,如果为了避免安全隐患,在它每次出现时都用final来修饰,会降低程序的执行效率,所以直接将其设为final来提高效率。

HashMap的源码,实现原理,底层结构。

hashMap底层是数组、链表和红黑树。
hashMap实质是Entry数组,每一个Entry包含key、value键值对和next属性。通过hash值计算index,如果该位置不存在Entry,则直接存放,如果该位置已有Entry,则比较地址值,地址值相同则调用equals方法比较key,若key相同,则直接取代,若地址值不同或key不同则新的Entry会放入到数组里,变成链表头部,并且next指向旧Entry,旧Entry下移变成链表。当链表长度达到阈值8时,链表变成红黑树。
hashMap的初始容量大小为16,当存放容量达到负载因子0.75时,hashMap会进行扩容,创建一个比原来大1倍的数组,并重新计算index,重新存放Entry。

扩展:
如何计算index?
通过key对象的hashCode方法得到hash值,通过hash值位运算length-1计算出index。
为什么不用取模,用位运算?
因为位运算效率更高。
为什么长度是2的n次法?
为了加快哈希计算和减少hash冲突,当长度为2的n次方时,hash值取模2n等于hash值与2n-1,可保证在计算index时,位运算一定比取模快,而2n-1为奇数,奇数的二进制最后一位为1,能保证hash&(length-1)的最后一位为0为1取决于hash值,可保证散列的均匀性,若长度为奇数,则length-1为偶数,那么计算出来的index一定为偶数,hashMap数组的奇数位置不会被存放,不止浪费了一半的存放空间,hash冲突的概率也变高。

注意:当hashMap的key为自定义类时,需重写hashCode方法和equals方法。

说说你知道的几个Java集合类:list、set、queue、map实现类

java中集合包括三大类:set,list,map。都处于java.util包,这三大类都是接口,都实现了Collection接口,也有各自的实现类。

List接口:可以重复,通过索引取出或加入数据,取出顺序与插入顺序一致,可以包含null元素。

list接口实现类有:ArrayList,Vector,LinkedList。

ArrayList:线程不同步。底层是数组结构array,查询快,增删慢。数组长度增长率50%。

Vector:底层是数组结构array,查询快,增删慢。线程同步是安全的,但因为每个方法加上了synchronized。所以效率慢于ArrayList。但增长率是100%,数据量大时,用Vector有一定优势。

LinkedList:线程不同步。底层是链表结构,增删快,查询慢。

Set接口:是无序集合,数据不可重复,实现类都是线程非安全的。(解决方案:Set set = Collections.synchronizedSet(Set 对象))

Set的接口实现类有:HashSet、LinkedHashSet和TreeSet。

HashSet:是Set接口最常用的实现类,底层数组,使用哈希表算法。插入速度较快,适用于少量数据的插入操作。比较两个对象相等需要满足:equls为ture和hashCode相同。如果要保证数据唯一,需要重写equals和hashCode方法。

LinkedHashSet:继承HashSet类,在HashSet的基础上,加了链表结构来保证数据的添加顺序,但效率变低,一般不建议使用。需要保证集合不重复,又需要记录数据的先后添加顺序时,才使用。

TreeSet:底层采用红黑树算法,拥有set接口的一般特性,又实现了SortSet接口。在TreeSet集合中只能存储相同类型对象的引用。TreeSet有两种重要的排序方式:自然排序和客户端排序。

Map接口:是一种把键对象和值对象进行映射的集合,其中每一个元素都包含了键对象和值对象。Map支持多级隐射,值对象也可以是Map类型的数据,键唯一,值可不唯一。

Map接口有两种实现:HashMap、HashTable和TreeMap。

HashMap:利用hash表实现,底层数组加链表加红黑树,线程不同步,允许key为null。

HashTable:与HashMap类似,但HashTable是线程同步的。

TreeMap:通过红黑树实现。继承自AbstractMap,是有序的key-value集合。实现了NavigableMap接口,可支持一系列的导航方法,比如返回有序的key集合。实现了Cloneable接口,可被克隆。实现了serializable,支持序列化。value可为null,key不能为null。线程不安全。

ps:
自然排序:实现了Comparable接口,可以调用对象的ComparableTo()方法比较集合大小,进行升序排序。

客户端排序:实现Comparator接口,通过重写compare方法来按自己的想法进行排序。

描述一下ArrayList和LinkedList各自实现和区别

ArrayList和linkedList 都实现了List接口,都是有序集合,可存储重复数据和null值,都是线程不同步的。区别:ArrayList:底层是数组array,增删慢,查询快;LinkedList底层是链表,增删快,查询慢。若增删只在集合尾部进行,可用ArrayList,若需要指定位置增删,则用LinkedList最快。

Java中的队列都有哪些,有什么区别。

队列:queue 。不允许插队,只运行头部取出,尾部插入。LinkedList实现了queue,且有两类队列,一类
是没有实现阻塞接口,一类是实现了堵塞接口。
ps:阻塞:当队列为空,获取元素会等待队列非空再取;当队伍不为空时,存储元素等待队伍可用。
注意:当有空时,再深入了解一下队列。

反射中,Class.forName和classloader的区别

class.forName()和classLoader都可以对类进行加载。
class.forName除了将类的字节码文件加载到jvm中以外,还会对类进行解释,第二个参数可选择是否初始化,执行类中的静态代码块;classLoader只将字节码文件加载到jvm中,不会执行static中的内容,只有调用newInstance才会去执行。

java新特性

版本太多了,面试有问到再说吧

Java数组和链表两种结构的操作效率,在哪些情况下(从开头开始,从结尾开始,从中间开始),哪些操作(插入,查找,删除)的效率高

一般情况下。
插入:从头开始插入:链表效率高;从尾部:数组效率高;从中间开始:链表效率高。
查找:都是数组效率高。
删除:与插入类似。

Java内存泄露的问题调查定位:jmap,jstack的使用等等

jps:主要用来输出jvm中运行的进程状态信息。
jstack:主要用来查看某个java进程内的线程栈信息。
jmap:用来查看堆内存使用状况。
注意:有空再巩固一下jvm的堆栈具体存放什么

String、Stringbuilder 和Stringbuffer区别。

从运行效率上来说:StringBuilder>Stringbuffer>String
String为字符串常量,重新赋值会创建新的对象,所以它最慢。Stringbuilder和Stringbuffer为字符串变量,但Stringbuffer的很多方法加了synchronized,所以效率比Stringbuilder慢,但是Stringbuffer线程安全,所以多线程建议用stringbuffer。
总结:String适用于少量字符串操作;
Stringbuilder:适用于单线程下在字符串缓冲区进行大量操作的情况。
Stringbuffer:适用于多线程下在字符串缓冲区进行大量操作的情况。

HashMap 和 HashTable的区别

相同的点:都实现了Map接口,都是无序集合,键唯一,值可不唯一。
不同点:HashMap是线程不安全的,并发条件下put操作可能会出现死锁。键和值都能为null,通过hashcode计算hash值,index计算用位运算,数组默认长度是16,扩容是扩大1倍,底层数组长度一定得是2的幂次方。
HashTable里的方法都加了synchronized关键字,是线程安全的但相应效率很低。键值不允许为null,编译不报错,但是运行会报空指针,计算index用取模运算,数组默认长度为11,扩容是扩大1倍再加1,对底层数组长度不做限制。

异常的结构,运行时异常和非运行时异常,各举个例子。

异常结构为树状,超类是throwable,下面有两大类:error和Exception。error是jvm相关问题,如系统奔溃、jvm报错等应用程序无法解决的问题。Exception有两类异常,一类是运行期异常,一类是非运行异常。运行期异常一般是编译者造成的逻辑上的错误,比如创建了长度为5的数组,却去查找数组索引6造成的索引越界异常。非运行异常一般是编译期就报错的异常,比如编译的创建了输入流,这时会有io流异常,必须抛出或者捕捉才能通过编译。

String a= “abc” String b = “abc” String c = new String(“abc”) String d = “ab” + “c” .他们之间用 == 比较的结果

== 比较的是地址值,而String是字符串常量,数据放在字符串常量池中,所以a,b,d三者间比较都为true,c是new出来的,new出来的对象放在堆内存中,所以c与a,b,d三者的地址值不同。

String类的常用方法。

比较字符串:equals() equalsIgnoreCase()
获取字符串长度:length()
去掉空格:trim()
包含字符串:contains() endWith() startWith()
切割字符串:spilt() subString() replace()

java引用类型有几种?

引用类型有三种:类、接口、数组。(默认值为null)

抽象类和接口的区别

被abstract修饰的class叫抽象类,抽象类不能创建实例对象。有抽象方法的类一定是抽象类,但抽象类不一定有抽象方法。抽象类的抽象方法必须在子类中实现,如果没有实现,子类也必须为抽象类。抽象类不能有抽象构造方法或抽象静态方法。

接口是抽象类的一种特例。jdk7时,可以有常量,抽象方法。jkd8时,可以有默认方法、静态方法;jdk9的时候,可以有私有方法。
区别:

  1. 抽象类可以有构造方法,接口中不能有构造方法。
  2. 抽象类可以有普通成员变量,接口不行。
  3. 接口中类的抽象方法可以是public,protected,但接口中的抽象方法只能是public。
  4. 接口和抽象类都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,接口定义的变量只能是public static final 。
  5. 一个类可以实现多个接口,但只能继承一个抽象类。
    在应用上,接口主要是应用于系统架构设计方法,定义模块间的通信规范。抽象类主要应用于在代码实现方面,实现代码的重用。

java的基本类型和字节大小

Java的基本类型:
整数型:
byte(8位,1个字节);
short(16位,2个字节);
int(32位,3个字节);
long (64位,4个字节)。
浮点型:
float(32位,4个字节)
double(64位,8个字节) 。
字符型:char(16位,2个字节)。
布尔型:boolean(8位或者32位,1个字节或4个字节,官方并没有明确给出)。

ps:8位=1个字节。

HashTable、HashMap、ConcurrentHashMap 底层实现原理与线程安全问题。

HashMap底层是哈希表和哈希算法。在多线程的情况下,使用hashMap的put操作会引起死循环,导致cpu利用率解决100%,是线程不安全的,并发情况下不能直接使用。HashTable与HashMap类似,是线程安全,通过synchronizd来保证线程安全,但在线程竞争激烈的情况下,hashtable效率非常低下,可能进入堵塞和轮询状态(线程一在使用put方法,线程2不能使用get也不能使用put方法)。ConcurrentHashMap是

sql优化

1.不要用select *查数据,需要什么字段就查什么字段。
2.给表加索引,优先考虑加where 和group by的。
3.少用in 或 not in,可用exists或between and代替。
4.少用or,可使用union代替。
5.模糊查询尽量不要用开头模糊,会使索引失效。
6.数据量大的时候,不要用where 1=1 这样的条件。
7.尽量不要用where 字段 is null 查询查询数据,可给字段加默认值0。
8.尽量不要在条件等号的左侧进行表达式、函数操作,会使索引失效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值