老虎证券社招java工程师

1.如何实现Arraylist的add方法,插入时数组满了怎么办,扩容的话新数组是多大
add方法源码:

public boolean add(E e) {
   ensureCapacityInternal(size + 1); 
   elementData[size++] = e;
   return true;
}
private void ensureCapacityInternal(int minCapacity) {
   modCount++;
   if (minCapacity - elementData.length > 0)
     grow(minCapacity);
}
private void grow(int minCapacity) {
   int oldCapacity = elementData.length;
  //将数组的长度增加原来数组的一半。
  int newCapacity = oldCapacity + (oldCapacity >> 1);  //其中oldCapacity是原来的容量大小,oldCapacity >> 1 为位运算的右移操作,右移一位相当于除以2,所以这句代码就等于int newCapacity = oldCapacity + oldCapacity / 2
  if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;。
  if (newCapacity - MAX_ARRAY_SIZE > 0)
    newCapacity = hugeCapacity(minCapacity);
   //数组最大位2^32
  elementData = Arrays.copyOf(elementData, newCapacity);
}


插入时满了数组会扩容,大小为原来的1.5倍

2.Springmvc的流程
1.springmvc将所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求进行真正的处理工作。
2.DispatcherServlet查询HandlerMapping,找到处理请求的Controller。
3.DispatcherServlet将请求提交到目标Controller。
4.Controller进行业务逻辑处理后,会返回一个ModelAndView。
5.Dispathcher查询ViewResolver视图解析器,找到ModelAndView对象指定的视图对象。
6.将页面渲染到浏览器客户端。

3.JVM内存模型,内存中有什么
1.Java堆:内存区域的唯一目的就是存放对象实例 。 

2.Java栈:存放 基本数据类型、对象引用类型
本地方法栈:本地方法栈类似与虚拟机栈,它们不同之处在于,虚拟机栈是为虚拟机执行的Java方法服务,
3.本地方法栈是为虚拟机使用到的Native方法服务;
一个Native Method就是一个java调用非java代码的接口。该方法的实现由非java语言实现,比如C
4.方法区:存放已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据

5.程序计数器:程序计数器是一块较小的内存分区,你可以把它看做当前线程所执行的字节码的指示器。程序执行时就是通过改变计数器的值来选择下一条需要执行的字节码指令


4.池有哪些,线程池,数据库连接池,用处
常用线程池:ExecutorService 是主要的实现类,其中常用的有 :
newSingleThreadPool()  单一线程池
newFixedThreadPool()   固定大小线程池
newcachedTheadPool()   可缓存线程池
newScheduledThreadPool() 定长线程池,支持定时及周期性任务执行。
作用:一.资源重用。避免频繁创建,释放连接引起的大量性能开销。它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
二.缩短系统响应时间。在初始化的过程中,池中已经创建了若干个连接备用。当有请求时,初始化工作已经完成,可直接利用现有的可用连接,减少了创建和释放连接的时间开销。
三.统一管理连接,避免数据库连接遗漏。释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                               long keepAliveTime,
                               TimeUnit unit,
                               BlockingQueue<Runnable> workQueue,
                               RejectedExecutionHandler handler) 


corePoolSize:线程池核心线程数量
maximumPoolSize:线程池最大线程数量
keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
unit:存活时间的单位
workQueue:存放任务的队列
handler:超出线程范围和队列容量的任务的处理程序

5.Hashcode如何重写

//Override注解
 public boolean equals(Object o) {
  if (this == o ) return true;
  if (o == null || getClass() != o.getClass()) return false; 
  Student student = (Student) o;
  if (age != student.age) return false;
  if (gender != student.gender) return false;
  return name != null ? name.equals(student.name) : student.name == null; 
} //Override注解 
public int hashCode() { 
 //name为String类,且String类的源码已经重写过hashCode() 
 int result = name != null ? name.hashCode() : 0;
 result = 31 *result + age;
 result = 31* result + (gender ? 1 : 0); 
 return result; 
}

6.垃圾回收机制,如何判断对象没用,可达性分析算法和引用计数算法在java中是搭配使用的吗? 
判断对象是否存活的方式:
一.引用计数算法: 给对象添加一个引用计数器,当有一个地方引用它时,计数器的值加1;当引用失效时,计数器值减1。任何计数器为0的对象都不可能再被使用。 但主流的java虚拟机并没有使用引用计数算 法来管理内存,原因是它很难解决对象间相互引用的问题。
二.可达性分析算法:通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(用图论的说法,从GC Roots到这个对象不可达)时,则证明此对象是不可用的。

7.处理无用对象的算法有哪些,其中复制算法中内存分配比例是多少,清理过程中新建的对象放在哪里
新生代的分配比例是Eden:Survivor1:Survivor2=8:1:1。新建的对象会放在Eden分区。  适合新生代较多的情况。

8.Volatile和sychronized的区别
volatile详解
 当一个变量定义为volatile后,它将具备两种特性:1. 可见性,2. 禁止指令重排序。
  编译器为了加快程序运行速度,对一些变量的写操作会现在寄存器或CPU缓存上进行,最后写入内存。而在这个过程中,变量的新值对其它线程是不可见的。
  当对volatile标记的变量进行修改时,会将其它缓存中存储的修改前的变量清除,然后重新读取。这里从哪读尚未明确,一般来说应该是先在进行修改的缓存A中修改为新值,然后通知其它缓存清除掉此变量,当其它缓存B中的线程读取此变量时,会向总线发送消息,这是存储新值的缓存A获取到消息,将新值传给B,最后将新值写入内存。
1.volatile修饰的变量在寄存器中的值是不确定的,而sychronized是锁定当前变量
2.volatile只能使用在变量级别,sychronized可以变量可以方法
3.volatile可见性,sychronized可见性和原子性
4.volatile不会阻塞线程,sychronized会阻塞线程

9.工作内存和主内存对应内存模型中哪块
 Java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存(可以与前面将的处理器的高速缓存类比),线程的工作内存中保存了该线程使用到的变量到主内存副本拷贝,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成。

10.Java基础的数据类型占多少字节
byte 1 short 2 int 4 long 8 float 4 double 8 char 2 boolean 不确定 

11.搜索树,b+树的应用场景,如何实现的
一棵 B 树必须满足以下条件:
1.若根结点不是终端结点,则至少有2棵子树
2.除根节点以外的所有非叶结点至少有 M/2 棵子树,至多有 M 个子树(关键字数为子树减一)
3.所有的叶子结点都位于同一层
文件系统和数据库系统中常用的B/B+ 树,他通过对每个节点存储个数的扩展,使得对连续的数据能够进行较快的定位和访问,能够有效减少查找时间,提高存储的空间局部性从而减少IO操作。他广泛用于文件系统及数据库中,如:
Windows:HPFS 文件系统
Mac:HFS,HFS+ 文件系统
Linux:ResiserFS,XFS,Ext3FS,JFS 文件系统
数据库:ORACLE,MYSQL,SQLSERVER 等中

12.Spring 的IOC为了解决什么问题
由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。解决了手动创建对象的问题,由框架自己去创建。


13.Hashmap是线程安全的吗?如何实现线程安全
线程不安全 。 使用效率低下的Hashtable 或者锁分段技术ConcurrentHashMap


14.ConcurrentHashmap是对什么分段
HashTable容器在竞争激烈的并发环境下表现出效率低下的原因,是因为所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。有些方法需要跨段,比如size()和containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁。这里“按顺序”是很重要的,否则极有可能出现死锁,在ConcurrentHashMap内部,段数组是final的,并且其成员变量实际上也是final的,但是,仅仅是将数组声明为final的并不保证数组成员也是final的,这需要实现上的保证。这可以确保不会出现死锁,因为获得锁的顺序是固定的。
ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构, 一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素, 每个Segment守护者一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。
也就是说 一个ConcurrentHashMap有一个Segment数组,一个Segment里包含一个HashEntry数组,一个HashEntry是一个链表结构的元素。


15.Hashmap的hashcode相同是如何添加数据,为何是用头插法
jdk1.8之前插入头,1.8插入尾。

16.Hashmap在什么时候扩容
扩容必须满足两个条件:
1、 存放新值的时候当前已有元素的个数必须大于等于阈值
2、 存放新值的时候当前存放数据发生hash碰撞(当前key计算的hash值换算出来的数组下标位置已经存在值)
hashmap扩容时会发生环链,之所以会导致HashMap出现死循环是因为多线程会导致HashMap的Entry节点形成环链,这样当遍历集合时Entry的next节点用于不为空,从而形成死循环

17.String s="a"+"b"和stringBuilder.append()的区别,常量池中存的是a,b,ab还是只有ab 
对于常量,编译时就直接存储它们的字面值而不是它们的引用,在编译时就直接讲它们连接的结果提取出来变成了"ab",也就是说常量池中只有ab
String每次都创建一个新的对象,而stringbuilder是在最后tostring时才创建一个新的对象。


18.定义一个final方法,它和其他方法有何区别
不能被重写,允许编译器将所有对此方法的调用转化为inline(行内)调用的机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用,例如保存断点,压栈等,这样可能会使你的程序效率有所提高,然而当你的方法主体非常庞大时,或你在多处调用此方法,那么你的调用主体代码便会迅速膨胀,可能反而会影响效率。


19.Spring创建bean和手工创建bean的区别
手工创建bean则是new一个对象,而spring创建bean通过ioc使用配置文件来创建一个对象


20.给10万条数据,有重复和不重复的,如何查出出现最多的前20条
通过hashcode分成多份,通过set去重,用最小堆(堆排序)来找最多的前20条


21.new一个包含多个字符串的数组,这句代码执行时,内存的哪些地方有变化
(自己理解,不一定对)数组存在堆中,new一个数组则是创建一个引用,存在栈中。而在数组中的多个字符串则是对象引用存在栈中,而字符串本身则存在堆中。


22.将long型的数据转换成int型,如何转换
1、强制类型转换 
long ll = 300000;  
int ii = (int)ll;  
2、调用intValue()方法 
long ll = 300000;  
int ii= new Long(ll).intValue();  
三、先把long转换成字符串String,然后在转行成Integer  
long ll = 300000;  
int ii = Integer.parseInt(String.valueOf(ll)); 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值