专门为了面试而学的 Java

转载 2016年08月30日 10:14:29

专门为了面试而学的 Java

1. hashmap hashtable

HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。

HashMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。

HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。

HashMap 的实例有两个参数影响其性能:“初始容量” 和 “加载因子”。容量 是哈希表中桶的数量,初始容量 只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。


继承关系

 

hashmap底层就是一个数组,然后数组里每个元素装了个链表。

这个数组元素称为bucket桶

图例

HashTable和HashMap区别

第一,继承不同。

第二,Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了,对HashMap的同步处理可以使用Collections类提供的synchronizedMap静态方法,或者直接使用JDK 5.0之后提供的java.util.concurrent包里的ConcurrentHashMap类。

第三,Hashtable中,key和value都不允许出现null值。在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。

第四,两个遍历方式的内部实现上不同。

Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。

第五,哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值( indexFor )。

第六,Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。

2. 为什么用枚举实现的单例是最好的方式

  • 枚举写法简单

  • 枚举自己处理序列化

在序列化的时候Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象。

3. jvm 内存模型

内存模型架构图
  • 程序计数器

每个线程有要有一个独立的程序计数器,记录下一条要运行的指令。线程私有的内存区域。如果执行的是JAVA方法,计数器记录正在执行的java字节码地址,如果执行的是native方法,则计数器为空。

  • 虚拟机栈

线程私有的,与线程在同一时间创建。管理JAVA方法执行的内存模型。

  • 本地方法区

和虚拟机栈功能相似,但管理的不是JAVA方法,是本地方法

  • 方法区

线程共享的,用于存放被虚拟机加载的类的元数据信息:如常量、静态变量、即时编译器编译后的代码。也称为永久代。

  • JAVA 堆

线程共享的,存放所有对象实例和数组。垃圾回收的主要区域。可以分为新生代和老年代(tenured)。

4. jdk 线程池

从中可以看出task1和task2依次最先执行,这时候currentPoolSize=2达到了corePoolSize,task3、task4、task5被送入缓冲队列,达到了workQueue最大值3,task6、task7、task8开启新的线程开始执行,此时currentPoolSize=5达到了maximumPoolSize,task9、task10根据AbortPolicy策略抛出异常,不再执行task9和task10。10秒钟后task1、task2….依次执行完毕释放线程,开始执行队列里的task3、task4、task5,最后task3、4、5执行完毕,所有任务完成。

JDK根据ThreadPoolExecutor配置好的线程池

5. Java 内存模型

内存模型描述了程序中各个变量(实例域、静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存中取出变量这样的底层细节。

JVM中存在一个主存区(Main Memory或Java Heap Memory),Java中所有变量都是存在主存中的,对于所有线程进行共享,而每个线程又存在自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作并非发生在主存区,而是发生在工作内存中,而线程之间是不能直接相互访问,变量在程序中的传递,是依赖主存来完成的。

JMM的最初目的,就是为了能够支持多线程程序设计的,每个线程可以认为是和其他线程不同的CPU上运行,或者对于多处理器的机器而言,该模型需要实现的就是使得每一个线程就像运行在不同的机器、不同的CPU或者本身就不同的线程上一样。

6. volatile 与 synchronized

在Java中,为了保证多线程读写数据时保证数据的一致性,可以采用两种方式:

  • 同步

如用synchronized关键字,或者使用锁对象.

  • volatile

使用volatile关键字

用一句话概括volatile,它能够使变量在值发生改变时能尽快地让其他线程知道.

volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.

volatile仅能使用在变量级别,synchronized则可以使用在变量,方法.

volatile仅能实现变量的修改可见性,但不具备原子特性,而synchronized则可以保证变量的修改可见性和原子性.

volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.

volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化.

7. 面试中遇到的问题

求一个无序数组的中位数,白板写 code

因为时间有限,没有多想,直接使用冒泡排序冒一半的数据,另一半保持无序。如果有更好的方法请告诉我谢谢!

数据库表的行转列

使用case when就可以实现了,但是要注意需要对每个case when做max,以及最后的group by,这样可以去除null值。

使用map = new hashmap 比 hashmap = new hashmap 的好处

一时间没想明白,因为觉得不会有人写成hashmap = new hashmap,就答了一下实现依赖抽象,方便复用和修改,减少栈存储之类乱七八糟的东西。。。如果有更好的答案也请告诉我谢谢

你必学知道的Java常考基础面试题

1.”static”关键字是什么意思?Java中是否可以覆盖(override)一个private或者是static的方法? 答案:“static”关键字表明一个成员变量或者是成员方法可以在没有所属的...

学java需掌握的面试基础……?

神静则心静 2017-03-14 07:33 21.final、finally、finalize的区别? final:被final修饰的类不能被继承、被final修饰的方法不能被重写(...

我们爱面试,一面一学-----JAVA堆、栈

烂俗的问题往往是最容易问到的问题,想必诸多面友都深有体会,因为我们和我们的面试官们都是俗人。但从另一方面来说,烂俗往往有着广阔的延伸空间,一次次让烂俗震惊你,不然于丹老师也就发不了财了。      ...

JAVA中两个专门操作枚举类型的容器类

在java中有两个容器来EnumSet和EnumMap,其他的方法看文档中对应的API。下面只是对这两个类的细节进行说明:   说明:普通的Map和Set也可以用来放枚举类型,但是用这两个类会更加...

在java环境中有一个专门的获取ttf文件的头信息的Font类

转自:  http://blog.csdn.net/connectionutils/article/details/7837528 SNO: 测试后, 完全可以工作, 里面有例子, 完全可以使用. ...
  • sno_guo
  • sno_guo
  • 2015年12月09日 21:09
  • 1926

[疯狂Java]集合:专门用于聚集操作的一次性集合——Stream(流)

1. Java 8新增的Stream特殊集合:     1) Stream,即流,和之前讲过的I/O流并非一种流,是一种特殊的有序、可重复集合,可以往流中放很多元素; !!它不属于Collecti...

Java IO操作——专门的数据输入类Scanner(java.util工具包中)的具体使用

学习目标  掌握Scanner类的使用  使用Scanner接收输入数据 Scanner类简介 在JDK1.5之后JAVA提供了专门的输入数据类,此类可以完成BufferedReader类的功能。也可...

张孝祥java面试宝典-2017

  • 2017年11月29日 10:04
  • 573KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:专门为了面试而学的 Java
举报原因:
原因补充:

(最多只允许输入30个字)