为了账号安全,请及时绑定邮箱和手机立即绑定

一次电话Java面试的问题总结

标签:
Java

面试涉及问题含有:

Java

JDK8新特性

集合(哈希冲突、HashMap的原理、自动排序的集合TreeSet)

多线程安全问题

String和StringBuffer

JVM

原理、运行流程、内部结构

Linux

查询含有某字符串内容的命令grep

查询进程、GC状态、杀死进程

Hadoop五种节点介绍

--------------------------------------------------------------------------------------------------------

JAVA:

1、JDK8新特性:

Lambda 表达式(闭包)− Lambda允许把函数作为一个方法的参数,函数作为参数传递进方法中。

lambda表达式的重要特征:

可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

可选的大括号:如果主体包含了一个语句,就不需要使用大括号。

可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

Lambda的设计 可以实现简洁而紧凑的语言结构。最简单的Lambda表达式可 由逗号分隔的参数列表、->符号和语句块 组成,例如:

Arrays.asList("a","b","d").forEach( e ->System.out.println( e ) );Arrays.asList("a","b","d").forEach( ( String e ) -> System.out.println( e ) );Arrays.asList("a","b","d").forEach( e -> {    System.out.print( e );    System.out.print( e );} );Stringseparator= ",";Arrays.asList("a","b","d").forEach(     ( String e ) -> System.out.print( e + separator ) );Arrays.asList("a","b","d").sort( ( e1, e2 ) -> e1.compareTo( e2 ) );等同于Arrays.asList("a","b","d").sort( ( e1, e2 ) -> {    int result = e1.compareTo( e2 );returnresult;} );

方法引用− 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

方法引用通过方法的名字来指向一个方法。

方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

方法引用使用一对冒号   ::  。

Java8使用两个新概念扩展了接口的含义:默认方法和静态方法。默认方法使得接口有点类似traits,不过要实现的目标不一样。默认方法使得开发者可以在 不破坏二进制兼容性的前提下,往现存接口中添加新的方法,即不强制那些实现了该接口的类也同时实现这个新加的方法。默认方法和抽象方法之间的区别在于抽象方法需要实现,而默认方法不需要。接口提供的默认方法会被接口的实现类继承或者覆写,例子代码如下:privateinterfaceDefaulable{defaultStringnotRequired(){return"Default implementation";     }        }privatestaticclassDefaultableImplimplementsDefaulable{}privatestaticclassOverridableImplimplementsDefaulable{@OverridepublicStringnotRequired(){return"Overridden implementation";    }}Defaulable接口使用关键字default定义了一个默认方法notRequired()。DefaultableImpl类实现了这个接口,同时默认继承了这个接口中的默认方法;OverridableImpl类也实现了这个接口,但覆写了该接口的默认方法,并提供了一个不同的实现。Java8带来的另一个有趣的特性是在接口中可以定义静态方法,例子代码如下:privateinterfaceDefaulableFactory{// Interfaces now allow static methodsstaticDefaulablecreate( Supplier< Defaulable > supplier ){returnsupplier.get();    }}下面的代码片段整合了默认方法和静态方法的使用场景:publicstaticvoidmain( String[] args ){    Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new);    System.out.println( defaulable.notRequired() );     defaulable = DefaulableFactory.create( OverridableImpl::new);    System.out.println( defaulable.notRequired() );}输出结果如下:Default implementationOverridden implementation

默认方法− 默认方法就是一个在接口里面有了一个实现的方法。

privateinterfaceDefaulableFactory{// Interfaces now allow static methodsstaticDefaulablecreate( Supplier< Defaulable > supplier ){returnsupplier.get();    }}

新工具− 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。

Stream API−新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

Date Time API− 加强对日期与时间的处理。

Optional 类− Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

Nashorn, JavaScript 引擎− Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

重复注解:

自从Java 5中引入 注解 以来,这个特性开始变得非常流行,并在各个框架和项目中被广泛使用。不过,注解有一个很大的限制是:在同一个地方不能多次使用同一个注解。Java 8打破了这个限制,引入了重复注解的概念,允许在同一个地方多次使用同一个注解。

在Java 8中使用@Repeatable注解定义重复注解,实际上,这并不是语言层面的改进,而是编译器做的一个trick,底层的技术仍然相同。可以利用下面的代码说明:

packagecom.javacodegeeks.java8.repeatable.annotations;importjava.lang.annotation.ElementType;importjava.lang.annotation.Repeatable;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;publicclassRepeatingAnnotations{@Target( ElementType.TYPE )@Retention( RetentionPolicy.RUNTIME )public@interfaceFilters {        Filter[] value();    }@Target( ElementType.TYPE )@Retention( RetentionPolicy.RUNTIME )@Repeatable( Filters.class )public@interfaceFilter {        String value();    };@Filter("filter1")@Filter("filter2")publicinterfaceFilterable{            }publicstatic void main(String[] args) {for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class) ) {            System.out.println( filter.value() );        }    }}

正如我们所见,这里的Filter类使用@Repeatable(Filters.class)注解修饰,而Filters是存放Filter注解的容器,编译器尽量对开发者屏蔽这些细节。这样,Filterable接口可以用两个Filter注解注释(这里并没有提到任何关于Filters的信息)。

另外,反射API提供了一个新的方法:getAnnotationsByType(),可以返回某个类型的重复注解,例如 Filterable.class.getAnnoation(Filters.class) 将返回两个Filter实例,输出到控制台的内容如下所示: filter1 filter2

2、集合:

哈希冲突:

(见博客:https://www.cnblogs.com/wuchaodzxx/p/7396599.html)

如果两个不同的元素,通过哈希函数得出的实际存储地址相同怎么办?也就是说,当我们对某个元素进行哈希运算,得到一个存储地址,然后要进行插入的时候,发现已经被其他元素占用了,其实这就是所谓的哈希冲突,也叫哈希碰撞。

哈希函数的设计至关重要,好的哈希函数会尽可能地保证 计算简单和散列地址分布均匀,但是,我们需要清楚的是,数组是一块连续的固定长度的内存空间,再好的哈希函数也不能保证得到的存储地址绝对不发生冲突。那么哈希冲突如何解决呢? 哈希冲突的解决方案有多种: 开放定址法(发生冲突,继续寻找下一块未被占用的存储地址),再散列函数法,链地址法,而HashMap即是采用了链地址法,也就是数组+链表的方式。

(1)开放定址法

这种方法也称再散列法,其基本思想是:当关键字 key的哈希地址 p=H( key)出现冲突时,以 p为基础,产生另一个哈希地址 p1,如果 p1仍然冲突,再以 p为基础,产生另一个哈希地址p2, …,直到找出一个不冲突的哈希地址 pi ,将相应元素存入其中。这种方法有一个通用的再散列函数形式:

Hi=( H( key) +d i ) % m   i=1, 2,…, n

其中 H( key)为哈希函数, m 为表长, d i 称为增量序列。增量序列的取值方式不同,相应的再散列方式也不同。主要有以下三种:

线性探测再散列

d i i=1, 2, 3, …, m-1

这种方法的特点是:冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。

二次探测再散列



作者:Java高级技术
链接:https://www.jianshu.com/p/0c8bb074165b


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
205
获赞与收藏
1008

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消