Java八股文持续跟新

一. 基础篇

手写二分查找

 1. 前提:有已排序好的数组A
 2. 定义左边界L,有边界R,确认搜索范围,循环执行二分查找(3,4两步)
 3. 获取中间索引M = (L+R)/2
 4. 中间索引的值A[M]与待搜索的值T进行比较
	A[M] == T 表示找到,返回中间索引
	A[M]  > T, 表示中间值右侧的元素都大于T,无需比较,中间索引左边找,M - 1设置位右边界,重新查找
	A[M]  < T, 表示中间值左侧的元素都小于T,无需比较,中间索引右边找,M + 1设置位左边界,重新查找
 5. 当L>R时,表示没有找到,结束循环
public class BinarySearch{
	public static void main (String[] args){
		int[] array = {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31};
		int target = 27;
		int idx = binarySearch(array , target);
		System.out.println(idx);
	}
	public static int binarySearcj(int[] a , int t){
		int l = 0 ;
		int r = a.length() - 1;
		int m;
		while(l <= r){
			m = (l + r) / 2;
			if (a[m] == t){
				return m;
			} else if(a[m] > t){
				r = m - 1;
			}else{
				l = m + 1;	
			}
		}
		return -1;
	}
}

排序算法

1.手写冒泡排序
public class BubbleSort{
	public static void main (String[] args){
		int[] array = {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31};
		bubble(array);
	}
	public static void bubble(int[] a){
		for(int i =  0; i < a.length() - 1 ; i++){
			for(int j = i + 1 ; j < a.length() ; j ++){
				if(a[i] > a[j]){
					int temp = a[i];
					a[i] = a[j];
					a[j] = temp;
				}
			}
		}
	}
} 
2.手写选择排序
public class SelectSort{
	public static void main (String[] args){
		int[] array = {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31};
		selection(array);
	}
	public static void selection(int[] a){
		for(int i = 0 ; i < a.length() - 1 ; i++){
			int s = i
			for(int j = i + 1 ; j < a.length() ; j++ {
				if(a[s] > a[j]){
					s = j;
				}
			}
			int temp = a[s];
			a[s] = a[i];
			a[i] = temp;
		}
	}
} 
3.手写插入排序
public class InsertSort{
	public static void main (String[] args){
		int[] array = {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31};
		insert(array);
	}
	public static void insert(int[] a){
		for(int i = 1 ; i < length - 1; i++){
			int temp = a[i]
			for(int j = i - 1 ; j >= 0 ; j--){
				if(a[j] > temp){
					a[j+1] = a[j];	
				}else{
					break;
				}
			}
			a[j+1] = temp;
		}
	}
} 
4.手写快速排序
public class QuicktSort{
	public static void main (String[] args){
		int[] array = {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31};
		quick(array,0,array.length());
	}
	public static int parttion(int[] a , int l ,int h){
		int pv = a[h];
		int i = l;
		for(int  j = l ; j < h ; j++){
			if (a[j] < pv){
				int temp = a[i]; 
				a[i] = a[j];
				a[j] = temp;
				i++;
			}
		}
		int t = a[h];
		a[h] = a[i];
		a[i] = t;
		return i;
	}
	public static void quick(int[] a , int l ,int h){
		if(l >= h){
			return;
		}
		int p  = parttion(a , l , h);
		quick(a , l , p - 1);
		quick(a , p + 1 , h);
	}
}  

ArrayList扩容机制

add()扩容机制
1.当数组为空时,插入新数据,会扩容长度10的新数组
2.当插入数组存满时,会触发扩容机制,本次扩容是上一次的1.5倍
3.旧数组的元素会重新插入新数组,且新插入的元素也会插入新数组
4.旧数组会被GC回收

addAll()扩容机制
1.当插入数据大于数组长度时,会产生新数组,产生的新数组会根据扩容机制长度与实际元素个数相比选择最大值当扩容长度.
2.旧数组的元素会插入新数组,且新插入的元素也会插入新 数组
3.旧数组会被GC回收

CopyOnWriteArrayList底层原理

1.ArrayList是线程非安全,所以产生了CopyOnWriteArrayList。
2.CopyOnWriteList是线程安全的
3.CopyOnWriteArrayList在添加元时,会复制一个新数组,写操作在新数组上进行,读操作还是在原数组上进行的
4.在新数组写操作时会添加ReentranLock,防止出现并发写入丢失数据的问题。
5.写操作结束之后会把原数组指向新数组
6.运用场景是读多写少

String,StringBuffer,StringBuilder的区别

1.String:这是指向常量,指向方法区的常量池,String是不可变的
2.StringBuffer:这是可变的,线程是安全的
3.StringBuilder:这也是可变的,但是线程不安全,运用在单线程

泛性中extends和super的区别

extends <T>:表示包括T在内的任何子类
super<T>:表示包括T在内的任何父类

==和equals的区别

1. ==:如果比较的是基本数据类型,那么比较的是值;如果比较的是引用类型,那么比较的是地址
2. equals:具体看各个类重写equals()方法之后的比较逻辑,例如String类,虽然是引用类型,但是String类中重写了equals(0,方法内部比较的是字符串的各个字符是否相等

ApplicationContext和BeanFactor有什么区别

ApplicationContext:继承于BeanFactory,所以它有BeanFactory的所有功能,但是他还继承其他接口EnvirtnmrntCapable,ListbleBeanFactory等等,他还有国际化,获取系统环境变量等等功能,但是BeanFactory没有这些功能

ArrayList和LinkedList区别

1.ArrayList:底层结构是数组,所以他适合随机查找
2.LinkedList:底层结构是双向链表,所以他适合删除,添加,它还额外实现了Deque接口,所以可以当作队列使用

B树和B+树的区别,为什么MySql使用B+树

B树:节点排序,一个节点可以存放多个元素,多个元素也排序
B+树:拥有B树的特点,叶子节点之间是链表,非叶子节点的元素在叶子节点都冗余,所以叶子节点存储了所有元素且排好序列

Explain语句中结果各个字段分别表示什么

 1. id:表示查询语句中每出现一个select关键字,MySql就会为它分配一个唯一的id值,某些子查询会被优化为join查询,那么出现的id会一样
 2. slect_type:SELECT关键字对应的查询类型
 3. table:表名
 4. partitions:匹配的分区信息
 5. type:针对表单的查询方式
 6. possible_keys:可能用到的索引
 7. key:实际用到的索引
 8. key_len:实际使用到的索引长度
 9. ref:当使用索引列等值查询时,与索引列进行等值匹配的对象信息
 10.rows:预估的需要读取的记录条数
 11.fiftered:某个表经过搜索条件过滤后剩余记录条数的百分比
 12.Extra:一些额外的信息,比如排序等

HashMap的扩容机制

 1. 先生成新数组
 2. 遍历老数组的每个位子的链表或者元素
 3. 如是是链表,则链表中的每个元素重新计算下标,并添加到新数组中去
 4. 如果是红黑树,则遍历红黑树,计算出红黑树中每个元素对应的在新数组的下标位置
	 1. 统计新数组每个下标位置的元素个数
	 2. 如果该位置的元素超过8,则生成一个新的红黑树,并且根节点添加到新数组对应的位置
	 3. 如果该位置的元素没有超过8,则生成一个新的链表,并且链表的表头添加到新数组对应的位置
 5. 所有元素转移完了之后,将新数组赋值给HashMap对象的table属性

Java死锁如何避免?

 1. 一个资源每次只能被一个线程使用
 2. 一个线程在阻塞等待某个资源时,不释放已占有资源
 3. 一个线程已经获得资源,在未使用完之前,不能被强行剥夺
 4. 若干线程形成头尾相接的循环结束等待资源
 5. 要注意加锁顺序,保证每个线程按同样的顺序进行加锁
 6. 要注意加锁时限,可以针对锁设置一个超时时间
 7. 要注意检查死锁,这是一种预防机制,确保第一时间发现死锁并进行解决

Java中的异常体系

 1. Java中的所有异常都继承一个父类Throwable
 2. Throwable有两个子类Excepton和Error
 3. Error表示非常严重的错误,比如SOM和OOM
 4. Exception表示异常,它有两个子类,RuntimeException和CheckException
 5. RuntimeException时在运行时出现的异常,可以进行捕获处理也可以不处理
 6. CheckException是检查异常,这是必须处理的异常,不然编译不通过

Java中有哪些类加载

 1. JDK自带三个类加载器:bootstrap ClassLoader,ExtClassLoader,AppClassLoader
 2. BootStrapClassLoader是ExtClassLoader父类加载器,默认负责加载%JAVA_HOME%/lib中下的jar包和class文件
 3. ExtClassLoader是AppClassLoader父类加载器,负责加载%JAVA_HOME%/lib/ext文件夹下的jar包和class文件
 4. AppClassLoader是自定义父类加载器的父类,负责加载classpath下的类文件

JVM有哪些垃圾回收算法

 1. 标记清除法
 	 1. 标记阶段:把垃圾内存标记出来
 	 2. 清除阶段:直接把垃圾内存回收
 	 3. 这种算法是比较简单,但是有个很严重的问题,就是会产生大量的内存碎片
 2. 复制算法:为了解决内存碎片问题,就产生复制算法,将内存分为两个大小相等的两半,每次只使用其中一半,垃圾回收时,将这一块的活对象全部拷贝到另一半,然后当前这一块内存就可以清除。但是这样存在一个严重问题就是浪费空间。
 3. 标记压缩算法:为了解决复制算法的缺陷,就提出了标记压缩算法。这种算法标记阶段和标记清除法是一样的,但是在完成标记之后,不是直接清理垃圾内存,而是将存活对象往一端移动,然后将边界以外的的所有内存直接清除

JVM中哪些是线程共享区

 堆区和方法区所有线程共享的,栈和本地方法栈,程序计数器是每个线程独有的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值