1.二叉树
二叉树的遍历排序实现
public class HeapSort {
int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51};
public HeapSort(){
heapSort(a);
}
public void heapSort(int[] a){
System.out.println("开始排序");
int arrayLength=a.length;
//循环建堆
for(int i=0;i<arrayLength-1;i++){
//建堆
buildMaxHeap(a,arrayLength-1-i);
//交换堆顶和最后一个元素
swap(a,0,arrayLength-1-i);
System.out.println(Arrays.toString(a));
}
}
private void swap(int[] data, int i, int j) {
// TODO Auto-generated method stub
int tmp=data[i];
data[i]=data[j];
data[j]=tmp;
}
//对data数组从0到lastIndex建大顶堆
private void buildMaxHeap(int[] data, int lastIndex) {
// TODO Auto-generated method stub
//从lastIndex处节点(最后一个节点)的父节点开始
for(int i=(lastIndex-1)/2;i>=0;i--){
//k保存正在判断的节点
int k=i;
//如果当前k节点的子节点存在
while(k*2+1<=lastIndex){
//k节点的左子节点的索引
int biggerIndex=2*k+1;
//如果biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在
if(biggerIndex<lastIndex){
//若果右子节点的值较大
if(data[biggerIndex]<data[biggerIndex+1]){
//biggerIndex总是记录较大子节点的索引
biggerIndex++;
}
}
//如果k节点的值小于其较大的子节点的值
if(data[k]<data[biggerIndex]){
//交换他们
swap(data,k,biggerIndex);
//将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
k=biggerIndex;
}else{
break;
}
}
步骤为:
- 创建一个堆
- 把堆顶元素(最大值)和堆尾元素互换
- 把堆的尺寸缩小1,并调用heapify(A, 0)从新的堆顶元素开始进行堆调整
- 重复步骤2,直到堆的尺寸为1
就是一次次选出最大的以后和堆尾交换,实现排序。
2.递归且按层级
简单来说,就是将一个二叉树按照层次结构安装递归的方法实现遍历。
通常来说,递归是指反复调用自身。
之前提示了一种map集合的实现,那么,我们来针对这种方法说一个思路:
map集合是键值对,实现,和遍历二叉树一样,要遍历到最后一个节点的子节点
二叉树实际上是一个个对象,每个对象中都有一个左节点和右节点。
其中要注意的就是这个对象的层级要判断。
那么,用map集合来保存这些对象,其中key为顺序,value为对象。
其中左子树均为:2k,右子树为2k+1
Map有这种集合的实现:
TreeMap
这个暂存,题目有点忘了。。。。。。。尴尬
3.空指针
1、最常见的空指针错误就是字符串变量未初始化,导致使用是报错
2、其次就是使用LIST等泛型时没有new ArrayList<>()容易报错空指针
3、然后就是在字符串为空时调用字符串方法如"".equel()等等都会报错,顺便说一句,如果要比较字符是否为空用str.equel(null)是会报错的,正确的使用方法是str==null。
4.当在栈区声明了引用类型的变量,而未让该引用变量指向堆区的内存时(即只声明未初始化),再操作该引用变量则出空指针错。
5.既声明又初始化了引用变量,但操作该引用变量的语句的作用域 不在 声明该引用变量的语句的作用域内。
6.map.get(“name”)为null时,抛出空指针异常。正确写法:
if (map.get(“name”)!=null) {
4.多数据表
当对多个数据表查询信息时的调优思路:
视图与索引,两种有一定区别,具体的思路:
1.合理使用索引
2.避免或简化排序
3.消除对大型表行数据的顺序存取
4.避免相关子查询
5.避免困难的正规表达式
6.使用临时表加速查询
详情,感谢
5.session共享
1)session复制
tomcat的session复制,可以实现session共享
优点:不需要额外开发,只需搭建tomcat集群即可
缺点:tomcat 是全局session复制,集群内每个tomcat的session完全同步(也就是任何时候都完全一样的) 在大规模应用的时候,用户过多,集群内tomcat数量过多,session的全局复制会导致集群性能下降, 因此,tomcat的数量不能太多,5个以下为好。
(2)session绑定
当用户A第一次访问系统时,tomcat1对其进行服务,那么,下次访问时仍然让tomcat1对其进行服务
(3)使用redis集中管理session
可以将用户的会话保存在redis中,每次从redis中查询用户信息,就可以很好的解决会话共享问题。
6.分布式
分布式是指将不同的业务分布在不同的地方。
从单机结构到集群结构,你的代码基本无需要作任何修改,你要做的仅仅是多部署几台服务器,每台服务器上运行相同的代码就行了。
但是,当你要从集群结构演进到微服务结构的时候,之前的那套代码就需要发生较大的改动了。所以对于新系统我们建议,系统设计之初就采用微服务架构,这样后期运维的成本更低。
但如果一套老系统需要升级成微服务结构的话,那就得对代码大动干戈了。所以,对于老系统而言,究竟是继续保持集群模式,还是升级成微服务架构,这需要你们的架构师深思熟虑、权衡投入产出比。
下面开始介绍所谓的分布式结构。分布式结构就是将一个完整的系统,按照业务功能,拆分成一个个独立的子系统,在分布式结构中,每个子系统就被称为“服务”。
这些子系统能够独立运行在web容器中,它们之间通过RPC方式通信。
举个例子,假设需要开发一个在线商城。
按照微服务的思想,我们需要按照功能模块拆分成多个独立的服务,如:用户服务、产品服务、订单服务、后台管理服务、数据分析服务等等。这一个个服务都是一个个独立的项目,可以独立运行。
如果服务之间有依赖关系,那么通过RPC方式调用。这样的好处有很多:
- 系统之间的耦合度大大降低,可以独立开发、独立部署、独立测试,系统与系统之间的边界非常明确,排错也变得相当容易,开发效率大大提升。
- 系统之间的耦合度降低,从而系统更易于扩展。我们可以针对性地扩展某些服务。假设这个商城要搞一次大促,下单量可能会大大提升,因此我们可以针对性地提升订单系统、产品系统的节点数量,而对于后台管理系统、数据分析系统而言,节点数量维持原有水平即可。
- 服务的复用性更高。比如,当我们将用户系统作为单独的服务后,该公司所有的产品都可以使用该系统作为用户系统,无需重复开发。
7.高访问量
详细链接:
1.首先需要解决网络带宽和Web请求的高并发,需要合理的加大服务器和带宽的投入,并且需要充分的利用系统中软件、硬件的缓存机制,将能缓存的内容都进行缓存存储,减少计算层和存储层的压力。
2.其次需要对业务服务器和业务支撑服务器进行合理的分层,并且采用并行计算和分布式算法对大量计算进行处理,并且在开发的过程中需要采用Java SDK中并发包(Concurrency)进行编码实现。
3.存储层需要采用分布式文件服务器和列式的存储服务器进行构建,支撑海量数据的存放和读取,并且还要对关系型数据进行深层次的配置参数优化。
4.我们还需要清楚的认识到,将来根据系统运行的状态以及平台中不同的业务场景循序渐进的进行调整和优化。
参考:
http://blog.youkuaiyun.com/qq_27379053/article/details/51035082
http://blog.youkuaiyun.com/xgt333/article/details/52167067
https://www.zhihu.com/question/20004877/answer/282033178