是最基本的接口,派生了两个子接口Set和List前端
无序且不可重复java
基于HashMap实现,全部元素都是保存在HashMap的key中,而value中保存了PRESENT。程序员
有序且可重复web
总结:面试
Map也是接口,但没有继承Collection接口。该接口描述了从不重复的键到值的映射。Map接口用于维护键/值对算法
基于哈希表实现,特色就是键值对的映射关系。一个key对应一个Value。HashMap中元素的排列顺序是不固定的。更加适合于对元素进行插入、删除和定位。spring
HashMap和Hashtable都实现了Map接口,但决定用哪个以前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。sql
Map m = Collections.synchronizeMap(hashMap);数据库
基于红黑树实现。TreeMap中的元素保持着某种固定的顺序。更加适合于对元素的顺序遍历。编程
迭代器是一种模式,它可使得对于序列类型的数据结构的遍历行为与被遍历的对象分离
Iterator对集合类中的任何一个实现类,均可以返回这样一个Iterator对象。能够适用于任何一个类。
由于集合类(List和Set等)能够装入的对象的类型是不肯定的,从集合中取出时都是Object类型,用时都须要进行强制转化,这样会很麻烦,用上泛型,就是提早告诉集合肯定要装入集合的类型,这样就能够直接使用而不用显示类型转换.很是方便.
优点在于更加简洁,更不容易出错,没必要关心下标的起始值和终止值
forEach不是关键字,关键字仍是for,语句是由iterator实现的,他们最大的不一样之处就在于remove()方法上
若是在循环的过程当中调用集合的remove()方法,就会致使循环出错,由于循环过程当中list.size()的大小变化了,就致使了错误。 因此,若是想在循环语句中删除集合中的某个元素,就要用迭代器iterator的remove()方法,由于它的remove()方法不只会删除元素,还会维护一个标志,用来记录目前是否是可删除状态,例如,你不能连续两次调用它的remove()方法,调用以前至少有一次next()方法的调用。
简单地说,就是一个变量和常量的关系。StringBuffer对象的内容能够修改;而String对象一旦产生后就不能够被修改,从新赋值实际上是两个对象
在String类中没有用来改变已有字符串中的某个字符的方法,因为不能改变一个Java字符串中的某个单独字符,因此在JDK文档中称String类的对象是不可改变的。然而,不可改变的字符串具备一个很大的优势:编译器能够把字符串设为共享的。
是对象不是原始类型.
为不可变对象,一旦被建立,就不能修改它的值.
对于已经存在的String对象的修改都是从新建立一个新的对象,而后把新的值保存进去.
String 是final类,即不能被继承.
是一个可变对象,当对他进行修改的时候不会像String那样从新创建对象
它只能经过构造函数来创建,
StringBuffer sb = new StringBuffer();
注意:不能经过赋值符号对他进行赋值.
sb = "welcome to here!";//error
对象被创建之后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer
中赋值的时候能够经过它的append方法.
sb.append("hello");
可预先分配指定长度的内存块创建一个字符串缓冲区。这样使用StringBuffer类的append方法追加字符 比 String使用 + 操做符添加字符 到 一个已经存在的字符串后面有效率得多。由于使用 + 操做符每一次将字符添加到一个字符串中去时,字符串对象都须要寻找一个新的内存空间来容纳更大的字符串,这无凝是一个很是消耗时间的操做。添加多个字符也就意味着要一次又一次的对字符串从新分配内存。使用StringBuffer类就避免了这个问题。
进程:每一个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。
线程:同一类线程共享代码和数据空间,每一个线程有独立的运行栈和程序计数器(PC),线程切换开销小。
线程和进程同样分为五个阶段:建立、就绪、运行、阻塞、终止。
多进程是指操做系统能同时运行多个任务(程序)。
多线程是指在同一程序中有多个顺序流在执行。
新建状态(New):当线程对象对建立后,即进入了新建状态,如:Thread t = new MyThread();
就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经作好了准备,随时等待CPU调度执行,并非说执行了t.start()此线程当即就会执行;
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的惟一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
阻塞状态(Blocked):处于运行状态中的线程因为某种缘由,暂时放弃对CPU的使用权,中止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的缘由不一样,阻塞状态又能够分为三种:
1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
2.同步阻塞 -- 线程在获取synchronized同步锁失败(由于锁被其它线程所占用),它会进入同步阻塞状态;
3.其余阻塞 -- 经过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程从新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
一种是继承Thread类,另一种是实现Runable接口
class MyThread extends Thread { private int i = 0; @Override public void run() { for (i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } } }
public class ThreadTest { public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 30) { Thread myThread1 = new MyThread(); // 建立一个新的线程 myThread1 此线程进入新建状态 Thread myThread2 = new MyThread(); // 建立一个新的线程 myThread2 此线程进入新建状态 myThread1.start(); // 调用start()方法使得线程进入就绪状态 myThread2.start(); // 调用start()方法使得线程进入就绪状态 } } } }
继承Thread类,经过重写run()方法定义了一个新的线程类MyThread,其中run()方法的方法体表明了线程须要完成的任务,称之为线程执行体。当建立此线程类对象时一个新的线程得以建立,并进入到线程新建状态。经过调用线程对象引用的start()方法,使得该线程进入到就绪状态,此时此线程并不必定会立刻得以执行,这取决于CPU调度时机。
class MyRunnable implements Runnable { private int i = 0; @Override public void run() { for (i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } } }
public class ThreadTest { public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 30) { Runnable myRunnable = new MyRunnable(); // 建立一个Runnable实现类的对象 Thread thread1 = new Thread(myRunnable); // 将myRunnable做为Thread target建立新的线程 Thread thread2 = new Thread(myRunnable); thread1.start(); // 调用start()方法使得线程进入就绪状态 thread2.start(); } } } }
让一个线程等待另外一个线程完成才继续执行。如A线程线程执行体中调用B线程的join()方法,则A线程被阻塞,知道B线程执行完为止,A才能得以继续执行。
让当前的正在执行的线程暂停指定的时间,并进入阻塞状态。在其睡眠的时间段内,该线程因为不是处于就绪状态,所以不会获得执行的机会。即便此时系统中没有任何其余可执行的线程,出于sleep()中的线程也不会执行。所以sleep()方法经常使用来暂停线程执行。
当调用了新建的线程的start()方法后,线程进入到就绪状态,可能会在接下来的某个时间获取CPU时间片得以执行,若是但愿这个新线程必然性的当即执行,直接调用原来线程的sleep(1)便可。
后台线程主要是为其余线程(相对能够称之为前台线程)提供服务,或“守护线程”。如JVM中的垃圾回收线程。
生命周期:后台线程的生命周期与前台线程生命周期有必定关联。主要体如今:当全部的前台线程都进入死亡状态时,后台线程会自动死亡
每一个线程在执行时都具备必定的优先级,优先级高的线程具备较多的执行机会。每一个线程默认的优先级都与建立它的线程的优先级相同。main线程默认具备普通优先级。
设置线程优先级:setPriority(int priorityLevel)。参数priorityLevel范围在1-10之间
当某个线程调用yiled()方法从运行状态转换到就绪状态后,CPU从就绪状态线程队列中只会选择与该线程优先级相同或优先级更高的线程去执行。
是指多线程环境下对共享资源的访问可能会引发此共享资源的不一致性。所以,为避免线程安全问题,应该避免多线程环境下对此共享资源的并发访问。
对共享资源进行访问的方法定义中加上synchronized关键字修饰,使得此方法称为同步方法。能够简单理解成对此方法进行了加锁,其锁对象为当前方法所在的对象自身。多线程环境下,当执行此方法时,首先都要得到此同步锁(且同时最多只有一个线程可以得到),只有当线程执行完此同步方法后,才会释放锁对象,其余的线程才有可能获取此同步锁,以此类推...
public synchronized void run() { }
使用同步方法时,使得整个方法体都成为了同步执行状态,会使得可能出现同步范围过大的状况,因而,针对须要同步的代码能够直接另外一种同步方式——同步代码块来解决。
synchronized (obj) { }
这三个方法主要都是用于多线程中,都是Object类中的本地方法。
在实际的多线程编程中,只有同步锁对象调这三个方法,才能完成对多线程间的线程通讯。
wait():致使当前线程等待并使其进入到等待阻塞状态。直到其余线程调用该同步锁对象的notify()或notifyAll()方法来唤醒此线程。
notify():唤醒在此同步锁对象上等待的单个线程,若是有多个线程都在此同步锁对象上等待,则会任意选择其中某个线程进行唤醒操做,只有当前线程放弃对同步锁对象的锁定,才可能执行被唤醒的线程。
notifyAll():唤醒在此同步锁对象上等待的全部线程,只有当前线程放弃对同步锁对象的锁定,才可能执行被唤醒的线程。
须要注意的是:
wait()方法执行后,当前线程当即进入到等待阻塞状态,其后面的代码不会执行;
notify()/notifyAll()方法执行后,将唤醒此同步锁对象上的(任意一个-notify()/全部-notifyAll())线程对象,可是,此时还并无释放同步锁对象,也就是说,若是notify()/notifyAll()后面还有代码,还会继续进行,知道当前线程执行完毕才会释放同步锁对象;
notify()/notifyAll()执行后,若是右面有sleep()方法,则会使当前线程进入到阻塞状态,可是同步对象锁没有释放,依然本身保留,那么必定时候后仍是会继续执行此线程,接下来同2;
wait()/notify()/nitifyAll()完成线程间的通讯或协做都是基于不一样对象锁的,所以,若是是不一样的同步对象锁将失去意义,同时,同步对象锁最好是与共享资源对象保持一一对应关系;
当wait线程唤醒后并执行时,是接着上次执行到的wait()方法代码后面继续往下执行的。
做用就是获得当前线程的对象。
经过currentThread()咱们能够轻易的就获得当前线程的名称,咱们还能够经过线程对象,获得其余的属性。
注意:
currentThread()方法返回的是对当前正在执行的线程对象的引用,this表明的是当前调用它所在函数所属的对象的引用
MySQL经常使用存储引擎:InnoDB适用于频繁维护修改插入等数据表,MyISAM适合少改写,少插入的频繁读取的表。经常使用InnoDB存储引擎
Innodb才支持事务
主要是为了解决并发状况下保持数据一致性的问题。
如下4个基本特征:
Atomic(原子性):事务中包含的操做被看作一个逻辑单元,这个逻辑单元中的操做要么所有成功,要么所有失败。
Consistency(一致性):只有合法的数据能够被写入数据库,不然事务应该将其回滚到最初状态。
Isolation(隔离性):事务容许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其余并行事务的修改相互独立。
Durability(持久性):事务结束后,事务处理的结果必须可以获得固化。
Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务
处理事务:spring的事务是经过“声明式事务”的方式对事务进行管理,即在配置文件中进行声明,经过AOP将事务切面切入程序,最大的好处是大大减小了代码量,提升了工做效率。
百度一下
MVC是model-view-controler的简称。也就是模型-视图-控制器。mvc是一种设计模式,他强制性的把应用程序的输入、处理和输出分开。mvc中的模型、视图、控制器分别担任着不一样的任务。
视图:视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并接受用户的输入。视图不进行任何业务逻辑处理。
模型:模型表示业务数据和业务处理。至关于javaBean。一个模型能为多个视图提供数据。这提升了应用程序的重用性。
控制器:当用户单击web页面中的提交按钮时,控制器接收请求并调用相应的模型去处理请求。而后根据处理的结果调用相应的视图来显示处理的结构。
MVC的处理过程:首先控制器接收用户的请求,调用相应的模型来进行业务处理,并返回数据给控制器。控制器调用相应的视图来显示处理的结构。并经过视图呈现给用户。如在项目中要对应MVC的话;View对应项目中的jsp,controler对应action,model对应service+dao层的业务逻辑和持久层的操做。
工做原理:
优化:
Hibernate对数据的缓存包括两个级:一级缓存,在Session的级别上进行,主要是对象缓存,以其id为键保存对象,在Session的生命期间存在;二级缓存,在SessionFactory的级别上进行,有对象缓存和查询缓存,查询缓存以查询条件为键保存查询结果,在SessionFactory的生命期间存在,默认地,Hibernate只启用一级缓存
优势:
Hibernate是JDBC的轻量级的对象封装,它是一个独立的对象持久层框架。Hibernate能够用在任何JDBC可使用的场合,例如Java应用程序的数据库访问代码,DAO接口的实现类,甚至能够是BMP里面的访问数据库的代码。
Hibernate是一个和JDBC密切关联的框架,因此Hibernate的兼容性和JDBC驱动,和数据库都有必定的关系,可是和使用它的Java程序,和App Server没有任何关系,也不存在兼容性问题。
Hibernate不能用来直接和Entity Bean作对比,只有放在整个J2EE项目的框架中才能比较。而且即便是放在软件总体框架中来看,Hibernate也是作为JDBC的替代者出现的,而不是Entity Bean的替代者出现的。
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了很是轻量级的对象封装,使得Java程序员能够为所欲为的使用对象编程思惟来操控数据库。
Hibernate能够应用在任何使用JDBC的场合。
Hibernate 使用Java 反射机制而不是字节码加强程序来实现透明性。
Hibernate 的性能很是好,由于它是个轻量级框架。映射的灵活性很出色。它支持各类关系数据库,从一对一到多对多的各类复杂关系。
易于上手和掌握。
sql写在xml里,便于统一管理和优化。
解除sql与程序代码的耦合。
提供映射标签,支持对象与数据库的orm字段关系映射
提供对象关系映射标签,支持对象关系组建维护
提供xml标签,支持编写动态sql。
Mybatis优点MyBatis能够进行更为细致的SQL优化,能够减小查询字段。
MyBatis容易掌握,而Hibernate门槛较高。
Hibernate优点Hibernate的DAO层开发比MyBatis简单,Mybatis须要维护SQL和结果映射。
Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
Hibernate数据库移植性很好,MyBatis的数据库移植性很差,不一样的数据库须要写不一样SQL。
Hibernate有更好的二级缓存机制,可使用第三方缓存。MyBatis自己提供的缓存机制不佳。
它基于IoC(Inversion of Control,反向控制)和AOP的构架多层j2ee系统的框架,但它不强迫你必须在每一层中必须使用Spring,由于它模块化的很好,容许你根据本身的须要选择使用它的某一个模块;它实现了很优雅的MVC,对不一样的数据访问技术提供了统一的接口,采用IoC使得能够很容易的实现bean的装配,提供了简洁的AOP并据此实现Transcation Managment,等等
事务控制:
低侵入式设计,代码污染极低
独立于各类应用服务器,基于Spring框架的应用,能够真正实现Write Once,Run Anywhere的承诺
Spring的DI机制下降了业务对象替换的复杂性,提升了组件之间的解耦
Spring的AOP支持容许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用
Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问
Spring并不强制应用彻底依赖于Spring,开发者可自由选用Spring框架的部分或所有
工做原理:
实现了MVC模式,层次结构清晰,使程序员只需关注业务逻辑的实现。
丰富的标签库,大大提升了开发的效率。
Struts2提供丰富的拦截器实现。
经过配置文件,就能够掌握整个系统各个部分之间的关系。
异常处理机制,只需在配置文件中配置异常的映射,便可对异常作相应的处理。
Struts2的可扩展性高。
面向切面编程的思想在Strut2中也有了很好的体现。最重要的体现就是拦截器的使用
第一步:发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求HandlerMapping查找 Handler,能够根据xml配置、注解进行查找
第三步:处理器映射器HandlerMapping向前端控制器返回Handler
第四步:前端控制器调用处理器适配器去执行Handler
第五步:处理器适配器去执行Handler
第六步:Handler执行完成给适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView,ModelAndView是springmvc框架的一个底层对象,包括Model和view
第八步:前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染,视图渲染将模型数据(在ModelAndView对象中)填充到request域
第十一步:前端控制器向用户响应结果工做流程:
优势: