一、算法题

1、判断一个数是否为2的N次幂

答:设这个数为n,然后用这个数的二进制和(n-1)的二进制做求与运算,如果所得的结果为0,那么即为二进制数。例如:10000000  与 01111111 ,两者取与计算为0

 

2、给定一个数组A(1-100)判断A里面是否有重复元素

答:定义一个hashmap集合,key存放A中的元素值,value存放该元素值出现的次数,假如用count表示,如果count>=2,说明有重复元素。

 

3、给定一个字符串ab_cd_e,要求字母放前面,下划线放后面。

答:

A、把字符串转换为字符数组(toCharArray)

B、定义一个StringBuilder,用来存放排序后字符

C、遍历字符数组,判断如果'a'<Char[i]<'z',就添加到sb中

D、再接着继续遍历字符数组,如果为空,退出;不为空,将元素添加到Sb中

E、将sb转化为字符串(toString())

 

4、判断一个链表是否是一个环

答:定义两个指针:

一个快指针(fast),假如每次移动两步;

一个慢指针(slow),假如每次移动一步。

判断两个指针能否相遇,如果能,则是一个环。

如果不能,快指针一定先指向NULL,则不成环。

class X {
    Boolean isExitsLoop(list head) {
        list slow=head;        
        list fast=head;
        
        while((fast && fast.head) != null) {       
            slow=slow.next;       
            fast=fast.next.next;       
            if(slow==fast){    
                break;
            }
        }
        return !(fast==null || fast.next==null);
    }
}

 

二、Java 基础题

1、HashMap与TreeMap的区别

答:

相同点:两者都是线程不安全的,都继承自AbstractMap

不同点:HashMap基于哈希表实现,使用HashMap要求添加的键明确定义hashcode()和equals()方法,适用于在Map中增删查元素,速度通常比TreeMAp要快一点,遍历结果是没有排序的。

TreeMap基于红黑树实现,适用于按自然顺序或自定义顺序遍历键(key),实现SortedMap接口,遍历得到的结果(键)是排过序的。

 

2、static成员是否能访问非静态成员

答:静态成员属于类,不需要生成对象就存在了,

而非静态需要生成对象才产生

所以,静态成员(属于类)不能直接访问非静态成员(属于对象)

 

3、TCP 与 UDP的区别

答:

A、TCP(传输控制协议),是面向连接的协议;UDP(用户数据报协议),是不面向连接的;

B、对系统资源的要求,TCP较多,UDP较少

C、TCP需要经过三次对话建立连接,UDP程序设计结构较为简单

D、TCP是流模式,UDP是数据报模式

E、TCP保证数据的正确性和顺序,UDP不能保证,可能丢失包。

 

Java 技术应用

1、JDBC、Ibatis(MyBatis)、Hibernate对比、以及优点缺点

答:

JDBC是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成

Hibernate、iBatis、myBatis都是Java的数据库DAO层框架。

与JDBC比较,Ibatis(MyBatis)优点如下:

A、减少了大量的代码量(61%);

B、架构级性能增强

C、sql语句与程序代码分离(便与修改)

D、增强了移植性

三者对比

(1) JDBC: 手动,手动写sql语句

delete、insert、update要将对象的值一个一个取出传到sql中,不能直接传入一个对象。

select:返回的是一个resultset,要从ResultSet中一行一行、一个字段一个字段的取出,然后封装到一个对象中,不直接返回一个对象。

(2) ibatis的特点:半自动化

sql要手动写

delete、insert、update:直接传入一个对象

select:直接返回一个对象 

(3) hibernate: 全自动

不写sql,自动封装

delete、insert、update:直接传入一个对象

select: 直接返回一个对象

总结:

JDBC更加灵活,更加有效率,系统运行速度快。但是用起来麻烦,不方便数据库的移植。

Ibatis(MyBatis)、Hibernate是关系数据库框架,开发速度快,更加面向对象,可以移植更换数据库,但是影响系统性能。

 

2、PrepareStatement 相比 statement优点

答:优势

A、相对比较安全,可以防止sql注入

B、有预编译功能,相同操作批量数据效率较高

PrepareStatement是预编译,使用Statement时sql中要进行很多的单引号拼接字符串,容易出错也比较麻烦。从安全方面来说,就是存在sql注入PrepareStatement传参数时候使用了占位符"?",解决了此类问题,(效率高)。

 

3、TCP为什么3次握手,四次挥手

答:TCP三次握手的目的是为了解决网络中存在延迟而重复分组的问题,防止server端一直等待,浪费资源。保证数据的可靠传输。

举个栗子(已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了),三次握手能解决此问题。client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。

 

四次挥手目的:

试想一下,假如现在你是客户端,你想断开跟Server的所有连接该怎么做?

第一步,你自己先停止向Server端发送数据,并等待Server的回复。但事情还没有完,虽然你自身不往Server发送数据了,但是因为你们之前已经建立好平等的连接了,所以此时他也有主动权向你发送数据;故Server端还得终止主动向你发送数据,并等待你的确认。其实,说白了就是保证双方的一个合约的完整执行!

 

名词解释:

seq:序列号

ACK:确认标志

SYN:请求同步标志

FIN:结束标志

三次握手:

(1) 客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报文1

(2) 当服务器接收到客户端发来的SYN时,会向客户端发送一个SYN+ACK数据包,这是三次握手中的第2个报文,这个报文同时带ACK标志和SYN标志。因此它表示对刚才客户端SYN报文的回应;同时又标志SYN给客户端,询问客户端是否准备好进行数据通讯。

(3) 客户端接收到,再次回应服务段一个ACK报文,确认发送。这是报文段3。

 

四次挥手:

(1) 先由客户端向服务器端发送一个FIN,请求关闭数据传输

(2) 当服务器接收到客户端的FIN时,向客户端发送一个ACK,其中ack的值等于FIN+SEQ

(3) 服务器向客户端发送一个FIN,告诉客户端应用程序关闭

(4) 客户端收到服务器端的FIN时,回复一个ACK给服务器端。其中ack的值等于FIN+SEQ

 

4、进程和线程含义及区别

答:(1)含义:

进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。

线程:是进程的一个实体,是CPU调度和分配的基本单位

(2)区别:

A、主要区别就是他们是不同操作系统的资源管理方式。

B、一个程序至少有一个进程,一个进程至少有一个线程

C、线程的划分尺度小于进程,使得多线程程序的并发性高

D、进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其他进程产生影响。但是线程没有独立的地址空间,一个线程死掉等于整个线程就死掉,因此多进程比多线程健壮。

E、线程在执行过程中与进程还是有区别的。每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

 

5、多线程什么情况下执行 wait 和 notify

答:调用wait和notify方法前,必须获得锁对象,也就是必须用在synchronized机制中的while循环中。

比如说两个线程A和B,当线程A获取到锁对象后,判断while循环条件是否满足,如果不满足,无法继续下一处理的时候,调用wait()方法。

在B线程中,B线程更改了某些条件,使得线程A的条件满足了,就调用notify()唤醒A

 

6、tomcat负载均衡

http://www.cnblogs.com/rocomp/p/4802396.html

 

7、Spring容器如何加载

https://my.oschina.net/chape/blog/136453

 

8、Servlet生命周期(什么时候destory)

答:servlet生命周期由javax.servlet.Servlet接口的init(),service()和destory()方法表达。Servlet被实例化之后,运行其init()方法,

请求到达时运行其service()方法,service()方法会自动派遣运行与请求对应的doXXX(doGet与doPost)等,当服务器决定将实例销毁的时候,

调用其destory()方法。

 

9、MySQL 底层实现,B+树原理

答:

(1)http://blog.csdn.net/u012978884/article/details/52416997

(2)B+树是为文件系统需要而设计的一种平衡查找树;http://blog.csdn.net/sykpour/article/details/25142759

 

10、10PB数据,每一条是一个qq号,统计出现频率最多的qq号

答:用hash的方法,hash(QQ) mod 10000,根据尾号取模把QQ分配到10000个文件中,这样每个文件的内存就是100MB,每个文件100MB,可以完全加载到内存中进行排序相同的QQ(同一个QQ字符串的hash值是一样的,这是解题关键)肯定存在相同的文件中,然后对每一个文件用HashMap(qq,qq.count)统计每个qq出现的次数。然后,记录每个文件的最大访问次数的QQ,最后,从10000个文件中找出来一个最大的即可。核心解题思想:hash(QQ) + 分而治之 (注:可否使用堆排序来实现呢?)

 

11、JVM新生代和老年代如何区分,新生代垃圾回收用什么算法,copy算法内存是怎么分的

答:

(1) JAVA堆中是JVM管理的最大的一块内存空间,主要存放对象实例。

详见米扑博客JVM 基础知识

Java 中堆被分为两个两块区域,即新生代(young,1/3)和老年代(old,2/3)

所谓的新生代和老年代是针对于分代收集算法来定义的。

区别:存放对象生命周期不同,垃圾回收机制不同。

新生代GC(minor gc) 主要是用来存放新生的对象,分为Eden和Survivor(from,to)两个区,这样划分是为了更好的管理堆内存中的对象,方便GC算法---复制coping算法来进行垃圾回收。

老年代GC(major gc)主要存放应用程序中生命周期长的内存对象,指发生在老年代的垃圾回收动作,所采用是的标记--整理算法

(2)新生代采用复制算法回收垃圾。

(3)copy算法基本思想:将内存分为两块,每次只用其中的一块,当这一块内存用完,就将还活着的对象复制到另一块上面。

具体地说,在GC开始的时候,对象只会存在到Eden区和From Survivor区中,而To Survivor区的内容是空的,紧接着进行GC,然后Eden区存活的对象都会被复制到“To”,而“From”区里面的对象年龄会加1,当年龄达到一定数值(年龄阈值),对象会被移动到老年代里,没有达到的被复制到“To”里面

因此经过GC后,Eden和“from”中的对象会被清空,这个时候,“From”和“To”交换角色,然后重复这样的过程,直到“To”区域被填满,“To”被填满后,会将所有的对象都移动到老年代中

 

12、HashMap的实现原理

(http://zhangshixi.iteye.com/blog/672697)

答:

(1) HashMap的概述

HashMap是基于哈希表的Map接口的非同步(非线程安全)实现,允许使用null值和null键,此类不保证映射的顺序。

(2) HashMap的数据结构

HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体

HashMap的底层就是一个数组结构,数组中的每一项又是一个链表

(3) HashMap的存取实现

存储(put): 当往HashMap中put元素的时候,先根据key的HashCode重新计算hash值,根据这个hash值得到这个元素在数组中的下标,如果该位置已经有其他元素,那么该位置的元素将已链表的形式存放,新加的放在链头。如果没有元素,就直接将该元素放在此位置

获取(get): HashMap中get元素时,首先计算key的hashCode,找到数组中对应位置的某一元素,然后通过key的equals方法在对应位置的链表中找到需要的元素。

总结:

HashMap在底层将Key-value当成一个整体进行处理,这个整体就是一个Entry对象。

HashMap底层采用一个Entry[]数组来保存所有的Key-value

对,当需要存储一个Entry对象时,会根据 hash算法来决定其在数组中的存储位置,再根据 equals方法决定其在数组位置上链表中的存储位置,当需要取出一个Entry对象时,先根据hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该对象。

 

13、数组和链表的比较

数组:数组是将元素在内存中连续存放,由于每个元素占用的内存相同,可以通过下标迅速访问数组中的任何元素,但是增加或者删除一个元素,就需要移动大量的元素,比较缓慢。

链表:链表中的元素在内存中不是顺序存储的,而是通过指针存在一起,每个节点包括两个部分,存储元素的数据域与存储下一结点地址的指针域

如果访问链表中元素,需要从第一个元素开始,一直找到需要的元素的位置,所以缓慢。但是增加删除元素,只需要修改指针就可以,速度较快。

区别:

(1)存储位置:

数组逻辑上相邻的元素在物理存储位置上也相邻,而链表不一定;

(2)存储空间:

链表存放的内存空间可以是连续的,也可以不连续,但是数组则是连续的一段存储空间;

(3)长度的可变性:

链表的长度可变,数组不可变

(4)访问方式:

数组可以随机访问其中元素,链表必须顺序访问。

优缺点:

1)数组

优点:使用方便,查询效率高,内存为一连续区域

缺点:大小固定,不适合动态存储,不方便动态添加。

2)链表

优点:可动态添加删除,大小可变

缺点:查询效率低。

 

14、ArrayList 和 Linkedlist 以及 Vector对比

答:ArrayList与Vector都是使用数组的方式进行存储,此数组元素数大于实际存储数据以便增加和插入元素,他们都允许按序直接索引元素,因此

查询较快,但是插入数组元素涉及到数组元素移动等内存操作,因此增删比较慢。Vector由于使用了synchronized方法,所以线程安全,但性能较差。

LinkedList使用双向链表的方式进行存储,按序索引数据需要向前或者向后遍历,因此查询比较慢;但是插入数据只需要记录本项的前后两项

即可,因此增删快,LinkedList也是线程不安全的。

 

15、准备一个了解或者感兴趣的新技术

 

 

面试题,说说对 Spring IOC和AOP的理解

在面试中,经常会问,说说你对 Spring IOC 和 AOP的理解,问题很宽泛,似乎不知道从何说起。

回答思路:

1. 先用通俗易懂的话解释下何为IOC和AOP

2. 各自的实现原理

3. 自己的项目中如何使用

 

以下是个人的一些总结,仅供参考。

1. IOC

许多应用都是通过彼此间的相互合作来实现业务逻辑的,如类A要调用类B的方法,

以前我们都是在类A中,通过自身new一个类B,然后在调用类B的方法,

现在我们把new类B的事情交给spring来做,在我们调用的时候,容器会为我们实例化。

 

2. IOC容器的初始化过程

资源定位,即定义bean的xml-------》载入--------》IOC容器注册,注册beanDefinition

IOC容器的初始化过程,一般不包含bean的依赖注入的实现,在spring IOC设计中,bean的注册和依赖注入是两个过程,,依赖注入一般发生在应用第一次索取bean的时候,但是也可以在xm中配置,在容器初始化的时候,这个bean就完成了初始化。

 

3. 三种注入方式,构造器、接口、setter注入,我们常用的是set注入

4. bean是如何创建---  工厂模式

5. 数据是如何注入-------反射

6. AOP

面向切面编程,在我们的应用中,经常需要做一些事情,但是这些事情与核心业务无关

比如,要记录所有update*方法的执行时间时间,操作人等等信息,记录到日志,

通过spring的AOP技术,就可以在不修改update*的代码的情况下完成该需求。

 

7. AOP的实现原理------代理

以下文章本人觉得可以很好地回答前两个问题,特此转载供读者参考:

http://blog.csdn.net/it_man/article/details/4402245     IOC的定义及实现原理---反射

http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html AOP的定义实现原理---代理

http://outofmemory.cn/code-snippet/3762/Spring-AOP-learn-example     AOP的应用的三种实现方式