2020-01-29

拜拜、爱过 提交于 2020-01-30 07:31:46

自己的一些面试总结

线程
多线程
线程的创建方式
1.继承Thread类创建线程
2.实现Runnable接口创建线程
3.使用Callable和future创建线程
4.使用线程池例如用Executor框架
线程怎么启动
Thread.start();//开启线程
Thread.run();当普通方法的方式调用
线程的状态(就绪、运行、阻塞、结束)
1.新建状态:当用new操作符创建一个线程时,线程还没有开始运行,此时线程处在新建状态
2.就绪状态:一个新创建的线程并不自动开始运行,要执行线程,必须调用线程start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态
3.运行状态
当线程获取cpu时间后,他才进入运行状态,真正开始执行run()方法
4,阻塞状态:线程运行过程中,肯峨眉号各种原因进入阻塞状态;
sleep方法进入睡眠状态
线程在等待某个触发条件
线程的同步
同步就是发出一个功能调试时,在没有得到结果之前,该调用就不返回或继续执行后续操作。
异步与同步相对,当一个异步过程调用发出后,调用者在没有得到结果之前,就可以继续执行后续操作。
线程、进程的区别
线程和进程都是一个时间段的描述,是cpu工作时间段的描述。
进程的颗粒太大,每次都要有上下的调度,保存,调出。线程就是把一个要实现的程序A分成了块abcd。
jdk1.8的新特性:
1、速度更快-红黑树
2、代码更少-lambda
3、强大的Stream API-Stream
4、便于并行-Parallel
5、最大化减少空指针异常-Optional
我们给接口添加一个非抽象的实现方法,只需要使用default关键字即可,这个特征叫做扩展方法:
interface Foemula{
double calculate(int a);
default double sprt(int a){
return Math.sqrt(a);
}}
sort排序
map映射;
Lambda表达式:
左侧:Lambda表达式的参数列表
右侧:Lambda表达式中所需执行的功能,即Lambda体
无参无返回值:
Runnable r2 = () -> System.out.println(“hello lambda”);
r2.run();
有一个参,无返回值:
(x)->System.out.println(x);
有两个以上参数,有返回值,并且lambda体中有多条语句
有两个以上的参数,有返回值,并且Lambda体中有多条语句 Comparator c1 = (x, y) -> {
System.out.print(Integer.compare(x, y)+“函数式接口”);
return Integer.compare(x, y);
} ;

springmvc和struts2的有略分析
共同点:他们都是表现层框架,都是基于MVC模型编写的
他们的底层都离不开原始servletAPI
他们处理请求的机制都是一个核心控制器
区别:
SpringMVC的入口是Servlet,而Struts2是Filter
Springmvc是基于方法设计的,而Struts是基于类,
SpringMVC使用更加简洁,同时还支持JSR303,处理ajax的请求更方便
java面试:
一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?
这个是可以的,一个“.java”源文件里面可以包含多个类,但是只允许有一个public类,并且类名必须和文件名一致
Java有没有goto?
goto是java中的保留字,目前并未使用
&和&&的区别?
&表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果为true,否则,只要有一个false,则返回结果为false
&&具有短路功能,如果第一个表达式为false,则不会计算第二个表达式。
在JAVA中如何跳出当前的多重嵌套循环?
要跳出多重循环,可以在外面的循环语句前定义一个标号,然后再里层循环提代码中使用带标号的break语句,即可跳出外层循环。
让外层的循环条件表达式的结果可以受到里层循环体代码的控制。
Switch语句能否作用在byte上,能否作用在long上,能否作用在string上?
switch只能是int,或只能转化为int型的byte,short,char,jdk1.7之后string也可以。
short s1= 1; s1 = (s1+1是int类型,而等号左边的是short类型,所以需要强转)1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
s1 = s1+1;s1 = s1+1;s1是short类型,1是int类型,s1会自动转换为int类型的1,与1相加后,得到int型的2,要向左侧的short类型s1看齐,既需要通过强制类型转换。正确写法:s1 = (short)(s1+1);
short s1 = 1; s1 += 1;正确!执行s1+=1其实执行的是s1 = (short)(s1+1);其中会有一个强制转换的过程。
char型变量中能不能存储一个中文汉字?为什么?
.java采用unicode编码,2个字节(16位)来表示一个字符,无论是汉字还是数字,字母,或其他语言都可以存储。2.char在java中是2个字节,所以可以存储中文。
用最有效率的方法算出2乘以8等於几?
最有效的2*8方法是:2<<3
使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
引用变量不能变,引用变量所指向的对象中的内容还是可以改变的 。
静态变量和实例变量的区别?
在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。
是否可以从一个static方法内部发出对非static方法的调用?
不可以,因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以再改对象上进行调用,而static方法调用时不用创建对象,可以直接调用。
解释内存中栈(stack)、堆(heap)和静态存储区的用法
通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;而通过new关键字和构造器创建的对象放在堆空间;栈空间操作最快但是小,通常大量的对象都是放在堆空间,整个内存包括硬盘上的虚拟内存都可以被当成堆空间来使用。
Integer与int的区别
1.Integer是int的包装类,int则是java的一种基本数据类型
2.Integer变量必须实例化后才能使用,而int变量不需要
3.Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值 。
4.Integer的默认值是null,int的默认值是0
Math.round(11.5)等於多少?Math.round(-11.5)等於多少?
ceil的意思是天花板,表示的就是向上取值
Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11
floor就是地板的意思
Math.floor(11.6)结果为11,Math.floor(-11.6)结果就是-12
round方法,表示的就是“四舍五入”,算法Math.round(11.5)的结果为12.Math.rounf(-11.5)结果就是-11
Overload和Override的区别?Overloaded的方法是否可以改变返回值的类型?
方法的重写(Override)和重载Overload是java多态性的不同表现。重写Override是父类和子类之间多态性的一种表现。重载Overload是一个类中堕胎的一种表现
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的 多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型。重载对返回类型没有特殊的要求。
数组中有没有length【】方法?string有没length【】方法?
数组中没有length()方法,有length的属性。string有length()方法。javascript中,获得字符串的长度是通过length属性得到的。
构造器不能被继承,因此不能被重写,但是可以被重载
string类是final类不可以被继承
接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concreteclass)?抽象类中是否可以有静态的main方法?
接口可以继承接口。抽象类可以实现接口,抽象类是可以继承的具体类。抽象类中可以有静态方法main方法
记住抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法
Java中实现多态的机制是什么?
继承的存在、子类重写父类的方法、父类引用变量指向子类对象
含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。
接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。
abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?
都不可以,因为abstract申明的方法是要求子类去实现的,abstract只是告诉你有这样一个接口,你要去实现,至于你的具体实现可以是native和synchronized,也可以不是,抽象方法是不关心这些事的,所以写这两个是没有意义的。
Array和ArrayList的区别?
array可以包含基本类型和对象类型,ArrayList只能包含对象类型
Array大小是固定的,arraylist的大小是动态变化的
ArrayList提供了更多地方法和特性,比如addall(),removeall(),iterator()
对于基本类型数据,集合适用自动装箱来减少编码工作量。
自动装箱是java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。
synchronized是java关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多有一个线程执行该段代码。
lock十一个接口,synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致思索现象发生;但是lock发生异常时,如果没有主动通过unlock()去释放锁,很可能造成死锁现象发生;
synchronized修饰静态方法以及同步代码块的synchronized (类.class)用法锁的是类,线程想要执行对应同步代码,需要获得类锁。
synchronized修饰成员方法,线程获取的是当前调用该方法的对象实例的对象锁。
重载和重写的区别
重载是让类以统一的处理方式处理不同数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型
java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义
重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同
重写:
父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某个方法与其父类有相同的名称和参数,我们说该方法被重写。
若子类中的方法与父类的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法
子类函数的访问修饰权限不能少于父类的。
举object类的方法:
clone():创建并返回对象的副本
equals(Object obj):
getclass()
notify():唤醒在此对象监视器上等待的单个线程
notifyall():唤醒所有
wait():等待
线程池就是事先创建若干个可执行的线程放入一个容器中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。
string、stringbuffer和stringbuilder的区别?
string是只读字符串,也就意味着string引用的字符串内容是不能改变的,stringbuffer和stringbuilder类表示的字符串对象可以直接进行修改。stringbuilder和stringbuffer的区别是在于它是单线程环境下使用的,因为他的所有方面都没有写synchronization修饰,因此它的效率比stringbuffer高一点
描述jvm加载class文件的原理机制?
jvm中类的装载是由类加载器和它的子类来实现的,java中的类加载器是一个重要的java运行时的系统组件,他负责在运行时查找和装入类文件中的类。
抽象类和接口有什么异同?
抽象类和接口都不能被实例化,但可以定义抽象类和接口类型的引用。一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类任然需要被声明为抽象类。接口比抽象类更抽象,抽象类中可以定义构造器,可以由抽象方法和具体方法,而接口中不能定义构造器,而且其中的方法偶都是抽象方法,抽象类中成员可以是private、默认、protected、public。而接口中的成员都是public
静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?
答:Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化,
静态变量和实例变量的区别?
静态变量是被static修饰符修饰的变量,也成为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。在java开发中,上下文类和工具类中通常会有大量的静态成员。
如何实现对象克隆?
两种方式:
实现cloneable接口并重写Object类中的clone()方法
实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

  1. ByteArrayOutputStream bout = new ByteArrayOutputStream();
  2.     ObjectOutputStream oos = new ObjectOutputStream(bout);  
    
  3.     oos.writeObject(obj);  
    
  4.     ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());  
    
  5.     ObjectInputStream ois = new ObjectInputStream(bin);  
    
  6.     return (T) ois.readObject();  
    
  7.     // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义  
    
  8.     // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源  
    

gc是什么?为什么要有gc?
gc就是垃圾收集的意思,Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc()或Runtime.getRuntime().gc(),但JVM可以屏蔽掉显示的垃圾回收调用。
java中的final关键字的用法?
1、修饰类:表示该类不能被继承
2、修饰方法:表示方法不能被重写;
修饰变量,表示变量只能一次赋值以后不能修改
数据类型之间的转换:
字符串类型转换为基本数据类型:parseXXX(String)或valueOf(String)
基本类型转换为字符串:一种方法是将基本数据类型与空字符串(””)连接(+)即可获得其所对应的字符串;另一种方法是调用String类中的valueOf(…)方法返回相应字符串
如何实现字符串的反转及替换?
public static String reverse(String originStr) {
if(originStr == null || originStr.length() <= 1)
return originStr;
return reverse(originStr.substring(1)) + originStr.charAt(0);
}
error和Exception的区别?
Error表示系统及的错误和程序不必处理的异常,很难处理。Exceptoin表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;
try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?
会执行,在方法调用前执行。java允许在finally中改变返回值的做法是不好的,因为如果存在finally代码块。try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕后再向调用者返回值
try来执行一段程序,如果出现异常就会抛出一个throw异常,这时候就用catch来捕捉它,或最后finally由缺省处理器来处理。
列出常见的异常?
classcastException(类转换异常)
indexOutOfBoundsException(下标越界异常)
null pointer Exception(空指针异常)
final、finally、finalize的区别?
final:如果一个类被声明为final,意味着它不能再派生出新的子类
finally:通常放在try。。catch后面,
finallize:Object类中定义的方法,hava中允许使用finalize()方法在垃圾回收集器将对象从内存中清除出去之前做必要的清理工作。
list、set、map:
list是线性结构的容器,适用于按数值索引访问元素的情形
set存储的零散的元素且不允许有重复元素
map是键值对映射容器
collection和collections的区别?
collection是一个接口,是set、list等容器的父接口;
collections是一个工具类,这些方法包括对容器的搜索、排序、线程安全化。
list、map、set三个接口,存取元素时各自的特点
list以特定索引来存取元素,可有重复元素。set不能存放重复元素。map保存键值对映射,关系可以是一对一或多对一。
通过sort方法的第二个参数传入一个comparator接口对象
相当于是传入一个比较对象大小的算法到sort方法中
由于java中没有函数指针、仿函数、委托这样的概念
因此要将一个算法传入一个方法中惟一的选择就是通过接口回调
sleep[]和wait[]的区别?
sleep[]方法是线程类的静态方法,导致线程暂停执行指定时间,将机会给其他线程,到时间后自动回复。wait时Object类的方法,只有针对此对象发出notify方法后本线程才进入对象锁定池准备获得对象锁进入就绪状态。
线程同步相关的方法:
wait:是一个线程处于等待状态,并且释放所持有的对象的锁。
sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉interruptedException异常
notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某个等待状态的线程,而是由jvm确定唤醒那个线程,并且与优先级无关;
notifyall():唤醒所有处于等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让他们竞争。
synchronization关键字用法?
synchronization关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问,可以用synchronization{}定义同步代码块
举例说明同步和异步?
正在写数据以后可能被另一个线程督导,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就必须进行同步存取。当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。事实上,所谓的同步就是指阻塞式操作,而异步就是非阻塞式操作。
就绪、运行、阻塞:
处于运行状态的线程可能因为cpu调度的原因回到就绪状态。
运行状态的线程可能因为i/o中端、线程休眠、调用了对象的wait方法而进入阻塞状态;进入阻塞状态的线程会因为休眠结束、调用了对象的notify或者notifyall方法或其他线程进入就绪状态。
io和nio两种方式实现文件拷贝
public class MyUtil {
private MyUtil() {
throw new AssertionError();
}
public static void fieldCopy(String source,string target) throws IOException{
try(Inputstream in = new FileInputStream(source)){
try(OutputStream out = new FieldOutputstream(target)){
byte[] buffer = new byte[4096];
int bytesToread;
while((bytesToRead = in.read(buffer))!= -1){
out.write(buffer, 0 , bytesToRead);}}}}
public static void fileCopyNIO(String source, String target) throws IOException {
try (FileInputStream in = new FileInputStream(source)) {
try (FileOutputStream out = new FileOutputStream(target)) {
FileChannel inChannel = in.getChannel();
FileChannel outChannel = out.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(4096);
while(inChannel.read(buffer) != -1) {
buffer.flip();
outChannel.write(buffer);
buffer.clear();
}
}
}
}
}
70、写一个方法,输入一个文件名和一个字符串,统计这个字符串在这个文件中出现的次数。
答:代码如下:
[java] view plain copy

  1. package com.lovo.demo;
  2. import java.io.BufferedReader;
  3. import java.io.FileReader;
  4. public class MyUtil {
  5. // 工具类中的方法都是静态方式访问的因此将构造器私有不允许创建对象(绝对好习惯)  
    
  6. private MyUtil() {  
    
  7.     throw new AssertionError();  
    
  8. }  
    
  9. /** 
    
  10.  * 统计给定文件中给定字符串的出现次数 
    
  11.  *  
    
  12.  * @param filename  文件名 
    
  13.  * @param word 字符串 
    
  14.  * @return 字符串在文件中出现的次数 
    
  15.  */  
    
  16. public static int countWordInFile(String filename, String word) {  
    
  17.     int counter = 0;  
    
  18.     try (FileReader fr = new FileReader(filename)) {  
    
  19.         try (BufferedReader br = new BufferedReader(fr)) {  
    
  20.             String line = null;  
    
  21.             while ((line = br.readLine()) != null) {  
    
  22.                 int index = -1;  
    
  23.                 while (line.length() >= word.length() && (index = line.indexOf(word)) >= 0) {  
    
  24.                     counter++;  
    
  25.                     line = line.substring(index + word.length());  
    
  26.                 }  
    
  27.             }  
    
  28.         }  
    
  29.     } catch (Exception ex) {  
    
  30.         ex.printStackTrace();  
    
  31.     }  
    
  32.     return counter;  
    
  33. }  
    
  34. }
    在开发中用到了那些设计模式?用在什么场合?
    工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作(多态方法)。当得到子类的实例后,开发人员调用基类中的方法而不必考虑到底返回的是哪一个子类的实例
    代理模式:给一个对象提供一个代理对象,并由代理对象控制元对象的引用。
    适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法再一起使用的类能够在一起工作。
    模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象发放,从而实现不同的业务逻辑。
    你在项目中那些地方使用到了xml?
    xml主要作用有两个方面:数据交换和信息配置。在做数据交换时,xml将数据用标签组装起来,然后压缩打包加密后通过网络传送给接收者,接受解密与解压缩后再从xml文件中还原相关的信息进行处理。
    Dao顾名思义就是一个为数据库或其他持久化机制提供了抽象接口的对象,在不暴漏数据库实现细节的前提下提供了各种数据操作。
    ORM对象关系映射是一种为了解决程序的面向对象模型与数据库的关系模型胡不匹配问题的技术;ORM是通过使用描述对象和数据库之间映射的元数据,将Java程序中的对象自动持久化到关系数据库中或者将关系数据库表中的行转换成Java对象,其本质上就是将数据从一种形式转换到另外一种形式。
    jdbc中如何进行事务处理?
    Connection提供了事务处理的方法,通过调用setAutoCommit可以设置手动提交事务;当事务完成后用commit()显示提交事务;如果事务处理过程中发生异常则通过rpllback()进行回滚。
  35. // 1. 加载驱动(Java6以上版本可以省略)
  36.         Class.forName("com.mysql.jdbc.Driver");  
    
  37.         // 2. 建立连接  
    
  38.         con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");  
    
  39.         // 3. 创建语句对象  
    
  40.         PreparedStatement ps = con.prepareStatement("insert into tb_user values (default, ?, ?)");  
    
  41.         ps.setString(1, "骆昊");              // 将SQL语句中第一个占位符换成字符串  
    
  42.         try (InputStream in = new FileInputStream("test.jpg")) {    // Java 7的TWR  
    
  43.             ps.setBinaryStream(2, in);      // 将SQL语句中第二个占位符换成二进制流  
    
  44.             // 4. 发出SQL语句获得受影响行数  
    
  45.             System.out.println(ps.executeUpdate() == 1 ? "插入成功" : "插入失败");  
    

事务的AICD指的是什么?
原子性、一致性、隔离性、持久性
session Factory对应Hibernate的一个数据存储概念,他是线程安全的,可以被多个线程并发访问。session Factory一般只会在启动的时候构建。session是一个轻量级非线程安全的对象(线程间不能共享session),她表示与数据库进行交互的一个工作单元。
sessoin的load和get方法?
① 如果没有找到符合条件的记录, get方法返回null,load方法抛出异常
②get方法直接返回实体类对象, load方法返回实体类对象的代理
③get方法只在一级缓存(内部缓存)中进行数据查找,如果没有找到对应的数据则越过二级缓存,直接发出SQL语句完成数据读取; load方法则可以充分利用二级缓存中的现有数据;
session加载实体对象的过程
1、session在调用数据库查询功能之前,首先会在缓冲中进行查询,在以及缓冲中,通过实体类型和主键进行查找,如果以及缓冲查找命中且数据状态合法,则直接返回
对于load方法,如果一级缓存查询失败则查询二级缓存,如果二级缓存命中则直接返回
如果之前的查询都未命中,则发出SQL语句,如果查询未发现对应记录则将此次查询添加到Session的NonExists中加以记录,并返回null
根据映射配置和SQL语句得到ResultSet,并创建对应的实体对象
对象纳入Session(一级缓存)管理
执行拦截器的onLoad方法(如果有对应的拦截器)
将数据对象纳入二级缓存
返回数据对象
linux常见的命令??
文件
touch:创建普通文件
ls:显示当前目录下文件
cd+路劲:切换当前工作目录。
rm:删除普通文件。
cp:拷贝
rmdir:删除空目录
find:查找文件
pwd:显示当前工作目录的绝对路径
head:显示文件前面一部分的内容
cat:显示文件全部内容,页面显示最后面的内容;也有合并文件的功能
tail:显示文件后面一部分内容
进程信息
ps:显示进程信息
kill pid:结束进程
jobs:显示后台挂起进程
&:在后台运行进程
系统管理
top:动态显示进程信息和系统运行统计信息
free:显示系统运行的统计信息:内存 缓存 缓冲 交换分区
网络通讯命令:
ping:测试网络连通性
netstat/ss:显示网络相关信息
service:管理系统运行的服务器
mail:查看、发送电子邮件
write:给用户发信息
tcpdump:抓包工具
sql语句的内外左右连接有些什么?
内连接:去两个表的交集,即字段相同。利用where条件语句进行连接
外连接:
左连接(left join)和右连接(right join)
语句:select* form A left Join B ON A.AId = B.Bnameid
java的基本类型?
整型:byte short int long
浮点型:float double
逻辑性:boolean
字符型:char
基本数据类型自动转换:byte->short,char->int->long
float->double
int->float
long->double。小可转大,大转小会失去精度。
java实现字符串反转?
1.利用stringbuffer的reverse的方法或者stringbulider的reverse的方法
2.for语句,–方法
stringbuffer和stringbulider的区别?
运行速度stringbulider比stringbuffer快
stringbulider线程上没有stringbuffer安全
stringbulider:适用于多线程下在字符缓冲区进行大量操作的情况
stringbuffer:适用多线程下在字符缓冲区进行大量操作的情况
java中的几种排序方法?
冒泡排序,选择排序重复地访问要排序的数列,一次比较两个元素。比较像领的两个元素,
快速排序:从数列中第出来一个个开始比,比他小的往前方,比他大的往后放,然后挨着比较。
选择排序:在未排序序列中找到最小的元素,存放到排序序列的起始位置。
再从剩余未排序元素中继续寻找最小元素,然后放到剩余的元素的开始,以此类推
归并排序
为什么依赖注入?
就是在调用一个类时,要对他进行实例化,生成一个对象是吧?但是如果要调用很多类,也就是需要依赖很多其他的类,要进行很多次实例化,太麻烦,所以就是要依赖注入到容器里面,ioc容器是个外界模型,他也是一个对象,只不过是把某个类,不管有多少依赖都放在这个容器中,可以解析出这个类的实例。所以依赖注入就是把依赖关系的类放入容器中,然后解析这个类,为什么要依赖注入,因为要控制反转啊,为什么控制反转,因为软件设计需要符合软件设计原理依赖倒置,就是要解耦
依赖倒置是什么?就是高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象,就是程序要依赖于抽象接口,不依赖于具体实现
解耦是什么?解耦就是说含有多个变量的数学方程变成能够用单个变量表示的方程组,变量不再同时共同直接影响一个方程的结果,耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。
Aop面向切面编程:通过动态代理和发射技术,已经基本实现了AOP的功能,如果我们只需要在方法执行前打印日志,则可以不实现end()方法,这样就可以控制打印的时机了。如果我们想让指定的方法打印日志,我们只需要在invoke()方法中加一个对method名字的判断,method的名字可以写在xml文件中,这样我们就可以实现以配置文件进行解耦了,这样我们就实现了一个简单的spring aop框架。
sql优化语句?
不使用子查询::先查外表再匹配内表,而不是先查内表t2,当外表的数据很大时,查询速度会非常慢。
避免函数索引:由于MySQL不像Oracle那样支持函数索引,即使d字段有索引,也会直接全表扫描。
用IN来替换OR(高效查询)
java中的集合?
colection集合:用来表示任何一种数据结构
collection:集合接口,指的是java.util.collection接口,是set、list和Queue接口的超类接口
Collections:集合工具类
list接口:关心的是索引,与其他集合相比,list特有的就是和索引相关的一些方法:get(int index)、add(index , object o)、indexof(object o)
ArrayList:可以将它理解为可以增长的数组,他提供快速插入和快速随机访问的能力
LinkedList中的元素之间是双链接的,当需要快速插入和删除时,LinkedList成为List中的不二选择。
HashMap:当需要键值对表示,又不关心顺序时可采用HashMap
mybatis原理分析:
Mybatis工作流程简述:
1.创建SqlsessionFactoryBuilder对象,调用build方法读取并解析配置文件,返回SqlsessionFatory对象
2、由SqlsessoinFactory创建Sqlsession对象,没有手动设置的话事务默认开启
3.调用Sqlsession中的api,传入Statement id和参数,内部进行复杂的处理,最后调用jdbc语句,封装结果返回。
使用Mapper接口:
有鱼面向接口编程的趋势,Mybatis也实现了 通过接口调用mapper配置文件中的SQL语句。
原生Mybatis原理分析
初始化工作
InputStream inputStream = Resources.getResourceAsStream(“mybatis-config.xml”);
//这一行代码正是初始化工作的开始。
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

ublic SqlSessionFactory build(InputStream inputStream) {
//调用了重载方法
return build(inputStream, null, null);
}

// 2.调用的重载方法
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
// XMLConfigBuilder是专门解析mybatis的配置文件的类
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//这里又调用了一个重载方法。parser.parse()的返回值是Configuration对象
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException(“Error building SqlSession.”, e);
} //省略部分代码
}

Configuration对象的结构和xml配置文件的对象几乎相同。

回顾一下xml中的配置标签有哪些:

properties(属性),settings(设置),typeAliases(类型别名),typeHandlers(类型处理器),objectFactory(对象工厂),mappers(映射器)等

初始化配置文件信息的本质就是创建Configuration对象,将解析的xml数据封装到Configuration内部的属性中。

springmvc常用注解
@controller
负责处理DispathServlet分发的请求,他爸用户请求的数据经过业务处理层处理之后封装成一个Model,然后再把该Model返回给对应的VIew进行展示。
五大常用算法:
穷举法:
简单粗暴,没有什么问题是搞不定的,只要你肯花时间。同时对于小数据量,穷举法就是最优秀的算法。
贪婪算法:
贪婪算法可以获取到问题的局部最优解,只要你肯花时间。同时对于小数据量,穷举法就是最优秀的算法。特点就是简单,能获取到局部最优解。
动态规划算法:
当最优化问题具有重复子问题和最优子结构的时候,就是动态规划出场的时候了。动态规划算法的核心就是提供了memory来缓冲重复子问题的结果,避免了地轨过程中的大量的重复计算。动态规划算法的难点在于怎么将问题转化为能够利用动态规划算来解决。当重复子问题的数目比较小时,动态规划的效果也会很差。如果问题存在大量的重复子问题的话,那么动态规划对于效率的提高是非常恐怖的。
分治算法:
分治算法的逻辑更简单了,就是一个词,分而治之。就是把一个大的问题分成若干个小问题,然后在小问题再继续往下分,一直到base cases,通过base cases的解决,一步步向上,最终解决最初的大问题。
回朔算法:
回朔算法是深度优先的策略的典型应用,回朔算法就是沿着一条走下去,如果此路不通,则回溯到上一个分岔路,再选一条路走,一直这样递归下去,知道遍历完所有的路劲。
分支限界算法:
分支限界算法就是广度优先的一个经典的例子。回朔法一般来说是遍历整个介空间,获取问题的所有解,而分支限界法则是获取一个解。
数据结构在java中的运用:
java工具包提供强大的数据结构。在java中的数据结构主要包括以下几种接口和类:
枚举:接口虽然本身不属于数据结构,但他在其他数据结构的范畴里应用很广。没经验接口定义了一种数据结构中取回连续元素的方式。
位集合:实现了一组可以单独设置和清除的位或标志
该类在处理一组布尔值的时候非常有用,你只要给每个值赋值一位,然后对位进行适当的设置或清除,就可以对布尔值进行操作了。
向量:和传统和数组非常相似,但是vactor的大小能根据需要的动态的变化。和数组一样,vactor对象的元素也能通过索引访问。使用vactor类最主要的好处就是在创建对象的时候不必给对象指定大小它的,大小会根据需要动态的变化。
栈:实现了一个后进先出的数据结构。可以把栈理解为对象的垂直分布的栈,当你添加一个新元素时,将新元素放在其他的元素的顶部。
字典:类是一个抽象类,它定义了键映射到值的数据结构。当你想要通过特定的键而不是整个数索引来访问数据的时候,这时候应该使用Dictonary。
由于Dictionary类是抽象类,所以它只是提供了键映射到值的数据结构,而没有提供特定的实现
哈希值:HashHtable:提供了一种在用户定义键结构的基础上来组织数据的手段
例:在地址列表的哈希表中,你可以根据邮政编码作为键来存储和排序数据,而不是通过人名。哈希表键的具体含义完全取决于哈希表的使用场景和它的包含的数据
属性:properties继承于Hashtable properties类表示了一个持久的属性集。属性列表中每个键及其对应值都是一个字符串,properties类被许多java类使用
spring ioc和aop的详细解释?
ioc就是典型的工厂模式,通过sessionfactory去注入实例
aop就是典型的代理模式的体现。
代理模式是常用的java代理模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类处理信息、过滤信息、把信息转发给委托类,以及事后处理消息等。
springioc是spring的核心,springaop是spring框架的重要组成部分。在传统的程序设计中,当调用者需要被调用者的协助时,通常由调用者来创建被调用者的实例。但在spring里创建被调用者的工作不再由调用者来完成。因此控制反转(IOC);创建被调用者实例的工作通常由spring容器来完成,然后注入调用者,因此也被称为依赖注入(DI),依赖注入和控制反转是同一个概念。

springioc原理以及举例:
我们先从IOC说起,这个概念其实是从我们平常new一个对象的对立面来说的,我们平常使用对象的时候,一般都是直接使用关键字类new一个对象,那这样有什么坏处呢?其实很显然的,使用new那么就表示当前模块已经不知不觉的和new的对象耦合了,而我们通常都是更高层次的抽象模块调用底层的实现模块,这样也就产生了模块依赖于具体的实现,这样与我们JAVA中提倡的面向接口面向抽象编程是相冲突的,而且这样做也带来系统的模块架构问题。很简单的例子,我们在进行数据库操作的时候,总是业务层调用DAO层,当然我们的DAO一般都是会采用接口开发,这在一定程度上满足了松耦合,使业务逻辑层不依赖于具体的数据库DAO层。但是我们在使用的时候还是会new一个特定数据库的DAO层,这无形中也与特定的数据库绑定了,虽然我们可以使用抽象工厂模式来获取DAO实现类,但除非我们一次性把所有数据库的DAO写出来,否则在进行数据库迁移的时候我们还是得修改DAO工厂类。

那我们使用IOC能达到什么呢?IOC,就是DAO接口的实现不再是业务逻辑层调用工厂类去获取,而是通过容器(比如spring)来自动的为我们的业务层设置DAO的实现类。这样整个过程就反过来,以前是我们业务层主动去获取DAO,而现在是DAO主动被设置到业务逻辑层中来了,这也就是反转控制的由来。通过IOC,我们就可以在不修改任何代码的情况下,无缝的实现数据库的换库迁移,当然前提还是必须得写一个实现特定数据库的DAO。我们把DAO普遍到更多的情况下,那么IOC就为我们带来更大的方便性,比如一个接口的多个实现,我们只需要配置一下就ok了,而不需要再一个个的写工厂来来获取了。这就是IOC为我们带来的模块的松耦合和应用的便利性。

那为什么说IOC很简单呢?说白了其实就是由我们平常的new转成了使用反射来获取类的实例,相信任何人只要会用java的反射机制,那么自己写一个IOC框架也不是不可能的。比如:
……
public ObjectgetInstance(String className) throws Exception
{
  Object obj = Class.forName(className).newInstance();
  Method[] methods = obj.getClass().getMethods();
  for (Method method : methods) {
    if (method.getName().intern() == “setString”) {
      method.invoke(obj, “hello world!”);
    }
  }
}
……
上面的一个方法我们就很简单的使用了反射为指定的类的setString方法来设置一个hello world!字符串。其实可以看到IOC真的很简单,当然了IOC简单并不表示spring的IOC就简单,spring的IOC的功能强大就在于有一系列非常强大的配置文件维护类,它们可以维护spring配置文件中的各个类的关系,这才是spring的IOC真正强大的地方。在spring的Bean定义文件中,不仅可以为定义Bean设置属性,还支持Bean之间的继承、Bean的抽象和不同的获取方式等等功能
反射实现AOP动态代理模式:
AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。
JdkDynamicAopProxy 同时实现了AopProxy和InvocationHandler接口,InvocationHandler是JDK动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。下面我们就通过分析这个类中实现的invoke()方法来具体看下Spring AOP是如何织入切面的。
AOP 在不修改源代码的情况下给程序动态统一添加功能。 这样就能够在一个项目及时要在中途需要这么一个功能,那也就只需修改配置文件和加一个类,而没有该已经写好的类的代码。aop明显增加了代码的复用性,也省去了重新测试的时间。
代理对象的方法 = 目标对象的目标方法 + 所有切面的通知。
织入:形成代理对象的方法的过程

通知:实际上就是切面中的方法。
切入点的理解:只有符合切入点的目标方法,才能加载通知。也就是调用切面的通知(方法)啦,看代码也就是说,切入点是控制代理对象内部的切面方法和目标对象的目标方法是否执行的条件。切面可以不止是一个。每个切面里面的通知即切面方法也是可以有很多的。
连接点的理解:所谓连接点,也就是目标对象或者代理对象之中的方法。为什么说2个都 可以呢?因为如果是jdk实现的动态代理的话,那么目标对象和代理对象要实现共同的接口,如果是cglib实现的动态代理的话,那么代理对象类是目标对象类的子类。都是一个方法啦。所以这么理解就OK的啦。
再加上代理对象,这个就比较简单了,测试代码有写注释啦。那么就是一共7个啦。
唯一漏掉的就是“引入”,这个是系统自己实现的,我们就没必要去深究了。

注意理解以下几个概念:
代理对象的方法 = 目标对象的目标方法 + 所有切面的通知。
织入:形成代理对象的方法的过程
springmvc实现原理案例分析:
web.xml文件中浏览器发送请求交给DispathcherServlet,根据请求找到指定的@Controller
@RequestMapping
并执行对应的查到的方法,返回modelView,然后交给视图解析器,再返回视图view,交给视图对象渲染,并返回浏览器展示信息
底层实现原理分析:request请求url–>前端控制器DispathCherServlet接口用户请求,查找Handler,处理器映射器HandlerMapping,返回一个执行链HandlerExecutionChain–>请求适配器执行handler(处理器适配器HandlerAdapater)执行–>handler处理器,平常叫Controller–>返回ModelAndview–>再到处理器适配器–>返回ModelAndView–>请求进行视图解析(视图解析器View resolver)–>返回view–>视图渲染将模型数据填充到request域–>view视图jsp freemarker excel pdf–>最后response响应
前后端分离大概可以从四个方面来理解:
1.交互形式
在前后端分离架构中,后端只需要负责按照约定的数据格式向前端提供可调用的API服务即可。前后端之间通过HTTP请求进行交互,前端获取到数据后,进行页面的组装和渲染,最终返回给浏览器
2.代码组织方式 前后端代码库分离,前端代码中有可以进行Mock测试(通过构造虚拟测试对 象以简化测试环境的方法)的伪后端,能支持前端的独立开发和测试。而后端 代码中除了功能实现外,还有着详细的测试用例,以保证API的可用性,降低 集成风险。
3.开发模式
产品经历/领导/客户提出需求
UI做出设计图
前后端约定接口&数据&参数
前后端并行开发(无强依赖,可– 前后端并行开发,如果需求变更,只要接口&参数不变,就不用两边都修改代码,开发效率高)
前后端集成
前端页面调整
集成成功
交付
4.数据接口规范流程
在开发期间前后端共同商定好数据接口的交互形式和数据格式。然后实现前后端的并行开发,这个步骤是前后端分离最为重要的!
1.前端工程师再开发完成之后可以独自进行mock测试。
2.后端也可以使用接口测试平台进行接口自测
常见面试题整理(操作系统):
线程和进程的区别:进程是具有一定功能的程序关于某个数据集合上的一次运动活动
线程是进程的实体,是cpu调度和分派的基本单位。它是比进程更小的能独立运行的基本单位。
一个进程可以有多个线程,多个线程也可以并发执行
线程同步的方式:
互斥量:采用互斥对象机制,只有拥有互斥的线程才有访问公共资源的权限。因为互斥对象只有一个,所以保证公共资源不会被多个线程同时访问
信号量:它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此线程的最大线程数量。
事件:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。
缓冲溢出:
缓冲溢出是指当计算机向缓冲区区填充数据时超出了缓冲区本身的容量,溢出的数据覆盖在合法数据上
危害:程序崩溃,导致拒绝服务
跳转并且执行一段恶意代码
什么是死锁?产生死锁的条件?
在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其他进程释放它或他们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗地讲就是两个或多个进程无限期的阻塞、相互等待的一种状态。
产生死锁的条件:
互斥条件:一个资源一次只能被一个进程使用
请求与保持条件:一个进程因请求资源而阻塞时,对已获得资源保持不放
循环等待条件:若干进程之间形成一种头尾相接的的环形等资源关系
进程有哪几种状态?
就绪状态:已获得除处理机以外的所需资源,等待分配处理机资源
运行状态:占用处理机资源运行,出于此状态的进程数小于等于cpu数
阻塞状态:进程等待某种条件,在条件满足之前无法执行
分页查询和分段查询:
段是信息的逻辑单位,它是根据用户的需要划分的,因此段对用户是可见的;页是信息的物理单位,是为了管理主存的方便而划分的,对用户是透明的
段的大小不固定,有它所完成的功能决定;页的大小固定,由系统决定
段是信息的逻辑单位,便于存储保护和信息共享,页的保护和共享受到限制
解决死锁的基本方法:预防死锁,避免死锁,检测死锁解除死锁。
软件工程:
软件指的是计算机系统中与硬件相互依赖的另一部分,包括程序、数据和有关的文档
需求分许是软件生命周期的一个重要阶段,分为4个方面:需求获取、需求分析、编写需求规格说明书及需求评审。
内聚性和耦合性是度量软件模块独立性的重要准则,软件设计时应力求高内聚,低耦合
软件工程三要素:方法、工具、过程
redis的数据结构:
redis存储的是:key,value格式的数据,其中key都是字符串,value有五种不同的数据结构
value数据结构:
1》字符串类型 string
2》哈希类型 hash:map格式
3》列表类型 list:linkedList格式。支持重复元素
4》集合类型set:不允许重复元素
5》有序集合类型 sortedest:不允许重复元素,且元素有顺序
字符串类型 string
1.存储:set key value
2.获取:get key
3.删除:del key
哈希类型:hash
1.存储:hset key field value
2.获取:hget key value:指定field对应的值
hgetall key:获取所有的field和value
3.删除:hdel key field
列表类型:list:可以添加一个元素到列表的头部或者尾部
1.添加:
1.lpush key value:将元素加入列表左边
2.rpush。。。:将元素加入到列表的右边
获取:
lrange key start end:范围获取
删除:
lpop key:删除列表最左边的元素,并将元素返回
rpop key:删除列表最右边的元素,并将元素返回
集合类型 set:不允许重复元素
存储:sadd key value:
获取:smembers key:获取set列表集合中所有元素
删除:srem key:删除set列表中的所有元素
有序集合 sorted set:不允许重复元素,且元素有顺序
存储:zadd key score value;
获取:zrange key start end;
删除:zren key value
通用命令:
keys*:查询所有的键
type key:获取键对应的value的类型
del key:删除指定的key value
持久化:
redis是一个内存数据库,当redis服务器重启,获取电脑重启,数据会丢失,我们可以将redis内存中的数据持久化保存到硬盘的文件中
redis持久化机制:
1.RDB:默认方式,不需要进行配置,默认就使用这种机制
在一定的间隔时间中,检测key的变化情况,然后持久化数据
编辑redis.windows.conf文件

after 900 sec(15 min) if at least 1 key changed

save 900 1
#after 300 sec(5 min) if at least 10 keys changed
save 300 10
重新启动redis服务器,并指定配置文件名称
ADF:日志记录的方式,可以记录每一条命令的操作。可以每一次命令操作后,持久化数据
编辑redis.windows.conf文件
appendonly no(关闭aof)–>appendonly yes (开启aof)
#appendfsync always:每一次操作都进行持久化
appendfsync everysec:每隔一秒进行一次持久化
appendfsync no:不进行持久化
jedis:
获取链接:
jedis jedis = new jedis();//如果使用空参构造,默认值"localhost",6379端口
//操作:
//存储
jedis.set(“username”,“zhangsan”);
//获取
jedis.get(“username”);
sout(username);
//可以使用setex()方法存储可以指定过期时间的key value;
jedis.setex(“activecode”,20,“hehe”);//将activecode:hehe键值对存入redis,并且20秒后自动删除该键值对。
//存储hash
jedis.hset(“user”,“name”,“lisi”);
jedis.hset(“user”,“age”,“23”);
//获取hash
String name = jedis.hget(“user”,“name”);
sout(name)
//关闭连接
jedis.close();
sql优化的几种方法:
对查询进行优化,尽量避免全表扫描,首先应考虑在where及order by设计的列上建立索引
尽量避免whehe子句中对字段进行null值判断,可以设置默认值0
尽量避免在where子句中使用!=或者<>操作符,否则会进行全表扫描
用具体的字段代替*,不要返回用不到的任何字段
尽可能使用varchar代替char,首先变长字段存储空间小,可以节省存储空间


1.1【插入单行】
insert [into] <表名> (列名) values (列值)
例:insert into Strdents (姓名,性别,出生日期) values (‘开心朋朋’,‘男’,‘1980/6/15’)

1.2【将现有表数据添加到一个已有表】
insert into <已有的新表> (列名) select <原表列名> from <原表名>
例:insert into tongxunlu (‘姓名’,‘地址’,‘电子邮件’)
select name,address,email
from Strdents

1.3【直接拿现有表数据创建一个新表并填充】
select <新建表列名> into <新建表名> from <源表名>
例:select name,address,email into tongxunlu from strdents

1.4【使用union关键字合并数据进行插入多行】
insert <表名> <列名> select <列值> tnion select <列值>
例:insert Students (姓名,性别,出生日期)
select ‘开心朋朋’,‘男’,‘1980/6/15’ union(union表示下一行)

2删
2.1【删除<满足条件的>行】
delete from <表名> [where <删除条件>]
例:delete from a where name=‘开心朋朋’(删除表a中列值为开心朋朋的行)

2.2【删除整个表】
truncate table <表名>
truncate table tongxunlu
注意:删除表的所有行,但表的结构、列、约束、索引等不会被删除;不能用语有外建约束引用的表
3改
update <表名> set <列名=更新值> [where <更新条件>]
例:update tongxunlu set 年龄=18 where 姓名=‘蓝色小名’

4查
4.1``精确(条件)查询
select <列名> from <表名> [where <查询条件表达试>] [order by <排序的列名>[asc或desc]]
4.1.1【查询所有数据行和列】
例:select * from a
说明:查询a表中所有行和列

4.1.2【查询部分行列–条件查询】
例:select i,j,k from a where f=5
说明:查询表a中f=5的所有行,并显示i,j,k3列
4.1.3【在查询中使用AS更改列名】
例:select name as 姓名 from a where xingbie=‘男’
说明:查询a表中性别为男的所有行,显示name列,并将name列改名为(姓名)显示
4.1.4【查询空行】
例:select name from a where email is null
说明:查询表a中email为空的所有行,并显示name列;SQL语句中用is null或者is not null来判断是否为空行
4.1.5【在查询中使用常量】
例:select name, ‘唐山’ as 地址 from Student
说明:查询表a,显示name列,并添加地址列,其列值都为’唐山’
4.1.6【查询返回限制行数(关键字:top percent)】
例1:select top 6 name from a
说明:查询表a,显示列name的前6行,top为关键字
例2:select top 60 percent name from a
说明:查询表a,显示列name的60%,percent为关键字

4.2.2【使用between在某个范围内进行查询】
例:select * from a where nianling between 18 and 20
说明:查询显示表a中nianling在18到20之间的记录
select * from a where name like ‘赵%’
说明:查询显示表a中,name字段第一个字为赵的记录

4.3.分组查询 4.3.1【使用group by进行分组查询】 例:select studentID as 学员编号,AVG(score) as 平均成绩 (注释:这里的score是列名) from score (注释:这里的score是表名) group by studentID 说明:在表score中查询,按strdentID字段分组,显示strdentID字段和score字段的平均值;select语句中只允许被分组的列和为每个分组返回的一个值的表达式,例如用一个列名作为参数的聚合函数 4.3.2【使用having子句进行分组筛选】 例:select studentID as 学员编号,AVG(score) as 平均成绩 (注释:这里的score是列名) from score (注释:这里的score是表名) group by studentID having count(score)>1 说明:接上面例子,显示分组后count(score)>1的行,由于where只能在没有分组时使用,分组后只能使用having来限制条件。 .4.多表联接查询
4.4.1内联接
4.4.1.1【在where子句中指定联接条件】
例:select a.name,b.chengji
from a,b
where a.name=b.name
说明:查询表a和表b中name字段相等的记录,并显示表a中的name字段和表b中的chengji字段
4.4.1.2【在from子句中使用join…on】
例:select a.name,b.chengji
from a inner join b
on (a.name=b.name)

4.4.2外联接
4.4.2.1【左外联接查询】
例:select s.name,c.courseID,c.score
from strdents as s
left outer join score as c
on s.scode=c.strdentID
说明:在strdents表和score表中查询满足on条件的行,条件为score表的strdentID与strdents表中的sconde相同
4.4.2.2【右外联接查询】
例:select s.name,c.courseID,c.score
from strdents as s
right outer join score as c
on s.scode=c.strdentID
说明:在strdents表和score表中查询满足on条件的行,条件为strdents表中的sconde与score表的strdentID相同

6、邻接矩阵与邻接表
邻接矩阵表示法:在一个一维数组中存储所有的点,在一个二维数组中存储顶点之间的边的权值
邻接表表示法:图中顶点用一个一维数组存储,图中每个顶点vi的所有邻接点构成单链表
对比
1)在邻接矩阵表示中,无向图的邻接矩阵是对称的。矩阵中第 i 行或 第 i 列有效元素个数之和就是顶点的度。
在有向图中 第 i 行有效元素个数之和是顶点的出度,第 i 列有效元素个数之和是顶点的入度。
2)在邻接表的表示中,无向图的同一条边在邻接表中存储的两次。如果想要知道顶点的度,只需要求出所对应链表的结点个数即可。
有向图中每条边在邻接表中只出现一次,求顶点的出度只需要遍历所对应链表即可。求入度则需要遍历其他顶点的链表。
3)邻接矩阵与邻接表优缺点:
邻接矩阵的优点是可以快速判断两个顶点之间是否存在边,可以快速添加边或者删除边。而其缺点是如果顶点之间的边比较少,会比较浪费空间。因为是一个 n∗n 的矩阵。
而邻接表的优点是节省空间,只存储实际存在的边。其缺点是关注顶点的度时,就可能需要遍历一个链表
10、B树
根据B类树的特点,构造一个多阶的B类树,然后在尽量多的在结点上存储相关的信息,保证层数尽量的少,以便后面我们可以更快的找到信息,磁盘的I/O操作也少一些,而且B类树是平衡树,每个结点到叶子结点的高度都是相同,这也保证了每个查询是稳定的。
B树和B+树的区别,以一个m阶树为例。

关键字的数量不同;B+树中分支结点有m个关键字,其叶子结点也有m个,其关键字只是起到了一个索引的作用,但是B树虽然也有m个子结点,但是其只拥有m-1个关键字。

存储的位置不同;B+树中的数据都存储在叶子结点上,也就是其所有叶子结点的数据组合起来就是完整的数据,但是B树的数据存储在每一个结点中,并不仅仅存储在叶子结点上。

分支结点的构造不同;B+树的分支结点仅仅存储着关键字信息和儿子的指针(这里的指针指的是磁盘块的偏移量),也就是说内部结点仅仅包含着索引信息。

查询不同;B树在找到具体的数值以后,则结束,而B+树则需要通过索引找到叶子结点中的数据才结束,也就是说B+树的搜索过程中走了一条从根结点到叶子结点的路径。

、数组和链表的区别。
从逻辑结构上来看,数组必须实现定于固定的长度,不能适应数据动态增减的情况,即数组的大小一旦定义就不能改变。当数据增加是,可能超过原先定义的元素的个数;当数据减少时,造成内存浪费;链表动态进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。
从内存存储的角度看;数组从栈中分配空间(用new则在堆上创建),对程序员方便快速,但是自由度小;链表从堆中分配空间,自由度大但是申请管理比较麻烦。
从访问方式类看,数组在内存中是连续的存储,因此可以利用下标索引进行访问;链表是链式存储结构,在访问元素时候只能够通过线性方式由前到后顺序的访问,所以访问效率比数组要低。
Java中new一个对象的步骤:
当虚拟机遇到一条new指令的时候,首先检查这个指令的参数是否能在常量池中能否定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过,就是验证是否是第一次使用该类。
类加载检查通过后,接下来虚拟机将会为新生的对象分配内存。对象所需的内存的大小在类加载完成后便可以完全确定,为对象分配空间的任务等同于把一块确定大小的内存从java堆中划分出来,目前常用的有两种方式,根据使用的垃圾回收器的不容使用不同的分配机制:
指针碰撞:如果java堆内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅把那个指针向空闲空间那边挪动一段域对象大小相等的距离
空闲列表:如果Java堆中的内存并不是规整的,已使用的内存和空间的内存是相互交错的,虚拟机必须维护一个空闲列表,记录上哪些内存块是可用的,在分配时候从列表中找到一块足够大的空间划分给对象使用。
内存分配完后,虚拟机需要将分配到的内存空间中的数据类型都 初始化为零值(不包括对象头);
虚拟机要 对对象头进行必要的设置
调用对象的init()方法
在线程 栈中新建对象引用 ,并指向堆中刚刚新建的对象实例。
因为有可能出现正在给A对象分配内存,指针还没有来得及修改,对象B又同时使用了原来的指针分配内存的情况,那么,解决这个问题有两种方案:
1. 分配内存空间的动作进行同步处理 :实际上虚拟机采用CAS配上失败重试的方式保证了更新操作的原子性。
2.内存分配的动作按照线程划分在不同的空间中进行: 为每个线程在Java堆中预先分配一小块内存 ,称为本地线程分配缓冲(Thread Local Allocation Buffer, TLAB)。
对对象的访问定位问题:
java程序需要通过栈上的reference数据来操作堆上的具体对象。定位:句柄访问、直接指针访问
类加载过程:类加载器接收到了加载的请求,他首先不会自己去尝试加载这个类
而是把这个请求委托给父类加载器去完成,每个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有父类加载器反馈说是自己无法完成这个加载请求时,子加载器其才会尝试自己去加载
1、加载–>2、验证–>3、准备–>4、解析–>5、初始化(先父后子)
创建对象:
1、在堆区分配对象需要的内存
分配的内存包括本类和父类的所有实例变量,但不包括任何静态变量
2、对所有实例变量赋默认值
将方法区内对实例变量的定义拷贝一份到堆区,然后赋默认值
3、执行实例初始化代码
初始化顺序是先初始化父类再初始化子类,初始化时先执行实例代码块然后是构造方法
4、如果有类似于Child c = new Child()形式的c引用的话,在栈区定于Child类型引用变量c,然后将堆区对象的地址赋值给它
需要注意的是,每个子类对象持有父类对象的引用,可在内部通过super关键字来调用父类对象,但在外部不可访问

使用两个栈来实现一个队列,完成队列的push和pop操作
实现思路:
利用栈last in first out 的特性,使用两个栈可以实现队列的pop和push操作。
push:往stack1中push元素。
pop:先判断stack2是否为空,若为空,将stack1中所有的元素pop至stack2中,取出stack2的栈顶元素pop出去;若不为空,直接取出stack2的栈顶元素pop出去
stack1.push(node);
int pop(){
if(stack2.empty()){
while(!stack1.empty()){
int t = stack1.top();
stack2.push(t);
stack1.pop();
}
}
int s = stack2.top();
stack2.pop();
return s;
}
private:
stack stack1;
satck stack2;
用两个队列来实现一个栈,完成栈的push和pop操作
队列中元素为int类型
思路:
定义一个队列为存储队列,另一个为中转队列
入栈时直接压入queue1中,出栈时先将除queue1最后一个元素外依次pop出队列,并压入queue2中,将留在queue1中的最后一个元素出对立即为出队元素,之后再将queue2中的元素压回queue1中。
void stackpush(queue &q1, int m){
q1.push(m);
}
int stackpop(queue &q1,queue &q2){
int num = q1.size();
for(int i = 0;i<num-1;i++){
q2.push(q1.front());
q1.pop();
}
int res = q1.front();
q1.pop();
for(int i = 0;i<q2.size();i++){
q1.push(q2.front());
q2.pop();
}
return res;
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!