元素的大小是固定的,并且能事先知道,用Array而不是ArrayList。java
若是能估计出存储的元素的数目,能够设置初始容量来避免从新计算hash值或者是扩容。程序员
为了类型安全,可读性和健壮性的缘由多使用泛型。同时,使用泛型还能够避免运行时的ClassCastException。面试
使用JDK提供的不变类(immutable class)做为Map的键能够避免为咱们本身的类实现hashCode()和equals()方法。算法
底层的集合其实是空的状况下,返回长度是0的集合或者是数组,不要返回null。spring
每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector、Stack、HashTable和Array。随着集合的普遍使用,Java1.2提出了囊括全部集合接口、实现和算法的集合框架。在保证线程安全的状况下使用泛型和并发集合类,Java已经经历了好久。它还包括在Java并发包中,阻塞接口以及它们的实现。sql
集合框架的部分优势以下:数据库
(1)使用核心集合类下降开发成本,而非实现咱们本身的集合类。编程
(2)随着使用通过严格测试的集合框架类,代码质量会获得提升。设计模式
(3)经过使用JDK附带的集合类,能够下降代码维护成本。数组
(4)复用性和可操做性。
Java1.5引入了泛型,全部的集合接口和实现都大量地使用它。泛型容许咱们为集合提供一个能够容纳的对象类型,所以,若是你添加其它类型的任何元素,它会在编译时报错。这避免了在运行时出现ClassCastException,由于你将会在编译时获得报错信息。泛型也使得代码整洁,咱们不须要使用显式转换和instanceOf操做符。它也给运行时带来好处,由于不会产生类型检查的字节码指令。
Collection为集合层级的根接口。一个集合表明一组对象,这些对象即为它的元素。Java平台不提供这个接口任何直接的实现。
Set是一个不能包含重复元素的集合。这个接口对数学集合抽象进行建模,被用来表明集合,就如一副牌。
List是一个有序集合,能够包含重复元素。你能够经过它的索引来访问任何元素。List更像长度动态变换的数组。
Map是一个将key映射到value的对象.一个Map不能包含重复的key:每一个key最多只能映射一个value。
尽管Map接口和它的实现也是集合框架的一部分,但Map不是集合,集合也不是Map。所以,Map继承Collection毫无心义,反之亦然。
若是Map继承Collection接口,那么元素去哪儿?Map包含key-value对,它提供抽取key或value列表集合的方法,可是它不适合“一组对象”规范。
(1)咱们可使用Iterator来遍历Set和List集合,而ListIterator只能遍历List。
(2)Iterator只能够向前遍历,而ListIterator能够双向遍历。
(3)ListIterator从Iterator接口继承,而后添加了一些额外的功能,好比添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
List<String> strList = new ArrayList<>(); //使用for-each循环 for(String obj : strList){ System.out.println(obj); } //using iterator Iterator<String> it = strList.iterator(); while(it.hasNext()){ String obj = it.next(); System.out.println(obj); }
使用迭代器更加线程安全,由于它能够确保,在当前遍历的集合元素被更改的时候,它会抛出ConcurrentModificationException。
HashMap在Map.Entry静态内部类实现中存储key-value对。HashMap使用哈希算法,在put和get方法中,它使用hashCode()和equals()方法。当咱们经过传递key-value对调用put方法的时候,HashMap使用Key hashCode()和哈希算法来找出存储key-value对的索引。Entry存储在LinkedList中,因此若是存在entry,它使用equals()方法来检查传递的key是否已经存在,若是存在,它会覆盖value,若是不存在,它会建立一个新的entry而后保存。当咱们经过传递key调用get方法时,它再次使用hashCode()来找到数组中的索引,而后使用equals()方法找出正确的Entry,而后返回它的值。下面的图片解释了详细内容。
其它关于HashMap比较重要的问题是容量、负荷系数和阀值调整。HashMap默认的初始容量是32,负荷系数是0.75。阀值是为负荷系数乘以容量,不管什么时候咱们尝试添加一个entry,若是map的大小比阀值大的时候,HashMap会对map的内容进行从新哈希,且使用更大的容量。容量老是2的幂,因此若是你知道你须要存储大量的key-value对,好比缓存从数据库里面拉取的数据,使用正确的容量和负荷系数对HashMap进行初始化是个不错的作法。
HashMap使用Key对象的hashCode()和equals()方法去决定key-value对的索引。当咱们试着从HashMap中获取值的时候,这些方法也会被用到。若是这些方法没有被正确地实现,在这种状况下,两个不一样Key也许会产生相同的hashCode()和equals()输出,HashMap将会认为它们是相同的,而后覆盖它们,而非把它们存储到不一样的地方。一样的,全部不容许存储重复数据的集合类都使用hashCode()和equals()去查找重复,因此正确实现它们很是重要。equals()和hashCode()的实现应该遵循如下规则:
(1)若是o1.equals(o2),那么o1.hashCode() == o2.hashCode()老是为true的。
(2)若是o1.hashCode() == o2.hashCode(),并不意味着o1.equals(o2)会为true。
咱们可使用任何类做为Map的key,然而在使用它们以前,须要考虑如下几点:
(1)若是类重写了equals()方法,它也应该重写hashCode()方法。
(2)类的全部实例须要遵循与equals()和hashCode()相关的规则。
(3)若是一个类没有使用equals(),你不该该在hashCode()中使用它。
(4)用户自定义key类的最佳实践是使之为不可变的,这样,hashCode()值能够被缓存起来,拥有更好的性能。不可变的类也能够确保hashCode()和equals()在将来不会改变,这样就会解决与可变相关的问题了。
Map接口提供三个集合视图:
(1)Set keyset():返回map中包含的全部key的一个Set视图。集合是受map支持的,map的变化会在集合中反映出来,反之亦然。当一个迭代器正在遍历一个集合时,若map被修改了(除迭代器自身的移除操做之外),迭代器的结果会变为未定义。集合支持经过Iterator的Remove、Set.remove、removeAll、retainAll和clear操做进行元素移除,从map中移除对应的映射。它不支持add和addAll操做。
(2)Collection values():返回一个map中包含的全部value的一个Collection视图。这个collection受map支持的,map的变化会在collection中反映出来,反之亦然。当一个迭代器正在遍历一个collection时,若map被修改了(除迭代器自身的移除操做之外),迭代器的结果会变为未定义。集合支持经过Iterator的Remove、Set.remove、removeAll、retainAll和clear操做进行元素移除,从map中移除对应的映射。它不支持add和addAll操做。
(3)Set<Map.Entry<K,V>> entrySet():返回一个map钟包含的全部映射的一个集合视图。这个集合受map支持的,map的变化会在collection中反映出来,反之亦然。当一个迭代器正在遍历一个集合时,若map被修改了(除迭代器自身的移除操做,以及对迭代器返回的entry进行setValue外),迭代器的结果会变为未定义。集合支持经过Iterator的Remove、Set.remove、removeAll、retainAll和clear操做进行元素移除,从map中移除对应的映射。它不支持add和addAll操做。
对于在Map中插入、删除和定位元素这类操做,HashMap是最好的选择。然而,假如你须要对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。
(1)二者都是基于索引的,内部由一个数组支持。
(2)二者维护插入的顺序,咱们能够根据插入顺序来获取元素。
(3)ArrayList和Vector的迭代器实现都是fail-fast的。
(4)ArrayList和Vector二者容许null值,也可使用索引值对元素进行随机访问。
(1)Vector是同步的,而ArrayList不是。然而,若是你寻求在迭代的时候对列表进行改变,你应该使用CopyOnWriteArrayList。
(2)ArrayList比Vector快,它由于有同步,不会过载。
(3)ArrayList更加通用,由于咱们可使用Collections工具类轻易地获取同步列表和只读列表。
Array能够容纳基本类型和对象,而ArrayList只能容纳对象。
Array是指定大小的,而ArrayList大小是固定的。
Array没有提供ArrayList那么多功能,好比addAll、removeAll和iterator等。尽管ArrayList明显是更好的选择,但也有些时候Array比较好用。
ArrayList和LinkedList二者都实现了List接口,可是它们之间有些不一样。
(1)ArrayList是由Array所支持的基于一个索引的数据结构,因此它提供对元素的随机访问,复杂度为O(1),但LinkedList存储一系列的节点数据,每一个节点都与前一个和下一个节点相链接。因此,尽管有使用索引获取元素的方法,内部实现是从起始点开始遍历,遍历到索引的节点而后返回元素,时间复杂度为O(n),比ArrayList要慢。
(2)与ArrayList相比,在LinkedList中插入、添加和删除一个元素会更快,由于在一个元素被插入到中间的时候,不会涉及改变数组的大小,或更新索引。
(3)LinkedList比ArrayList消耗更多的内存,由于LinkedList中的每一个节点存储了先后节点的引用。
ArrayList、HashMap、TreeMap和HashTable类提供对元素的随机访问。
Vector、HashTable、Properties和Stack是同步类,因此它们是线程安全的,能够在多线程环境下使用。Java1.5并发API包括一些集合类,容许迭代时修改,由于它们都工做在集合的克隆上,因此它们在多线程环境中是安全的。
队列容许先进先出(FIFO)检索元素,但并不是老是这样。Deque接口容许从两端检索元素。
栈与队列很类似,但它容许对元素进行后进先出(LIFO)进行检索。
Java.util.Collections是一个工具类仅包含静态方法,它们操做或返回集合。它包含操做集合的多态算法,返回一个由指定集合支持的新集合和其它一些内容。这个类包含集合框架算法的方法,好比折半搜索、排序、混编和逆序等。
若是咱们须要对一个对象数组进行排序,咱们可使用Arrays.sort()方法。若是咱们须要排序一个对象列表,咱们可使用Collection.sort()方法。两个类都有用于天然排序(使用Comparable)或基于标准的排序(使用Comparator)的重载方法sort()。Collections内部使用数组排序方法,全部它们二者都有相同的性能,只是Collections须要花时间将列表转换为数组。
在做为参数传递以前,咱们可使用Collections.unmodifiableCollection(Collection c)方法建立一个只读集合,这将确保改变集合的任何操做都会抛出UnsupportedOperationException。
经过bean 定义中的scope属性来定义。
scope配置项有5个属性,用于描述不一样的做用域。
① singleton【默认】
使用该属性定义Bean时,IOC容器仅建立一个Bean实例,IOC容器每次返回的是同一个Bean实例。
② prototype
使用该属性定义Bean时,IOC容器能够建立多个Bean实例,每次返回的都是一个新的实例。
③ request
该属性仅对HTTP请求产生做用,使用该属性定义Bean时,每次HTTP请求都会建立一个新的Bean,适用于WebApplicationContext环境。
④ session
该属性仅用于HTTP Session,同一个Session共享一个Bean实例。不一样Session使用不一样的实例。
⑤ global-session
该属性仅用于HTTP Session,同session做用域不一样的是,全部的Session共享一个Bean实例。
编程式事务管理:这意味你经过编程的方式管理事务,给你带来极大的灵活性,可是难维护。
声明式事务管理:这意味着你能够将业务代码和事务管理分离,你只需用注解和XML配置来管理事务。
控制反转(IOC) : 传统应用程序是由咱们本身在对象中主动控制去直接获取依赖对象,如今由容器帮咱们查找及注入依赖对象,对象只是被动的接受依赖对象,因此是控制反转。
依赖注入:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。经过依赖注入机制,咱们只须要经过简单的配置,而无需任何代码就可指定目标须要的资源,完成自身的业务逻辑,而不须要关心具体的资源来自何处,由谁实现。
实现方式:构造器注入、Setter方法注入、接口注入。注解装配在默认状况下是不开启的,为了使用注解装配,咱们必须在Spring配置文件中配置 context:annotation-config/元素。
a、Bean 组件
b、Context 组件
c、Core 组件
a、用户向服务器发送request请求,请求被SpringMVC中央控制器DispatcherServlet捕获;
b、DispatcherServlet对请求URL进行解析,获得请求资源标识符(URI)。而后根据该URI,调用HandlerMapping映射处理器,将请求发送给指定的Controller。
c、 Controller执行完成后,将返回的数据信息封装到ModelAndView对象中,最后经过ViewResolver视图解析器选择一个合适的View 渲染视图返回界面。
a、DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
b、未提交读(read uncommited) : 脏读,不可重复读,虚读都有可能发生 。是最低的事务隔离级别,它容许另一个事务能够看到这个事务未提交的数据。
c、已提交读 (read commited): 避免脏读。可是不可重复读、虚读有可能发生 。保证一个事物提交后才能被另一个事务读取。另一个事务不能读取该事物未提交的数据。Oracle 默认
d、可重复读 (repeatable read): 这种事务隔离级别能够防止脏读,不可重复读。可是可能会出现幻象读。它除了保证一个事务不能被另一个事务读取未提交的数据以外还避免了如下状况产生(不可重复读)。Mysql 默认
e、串行化的 (serializable) : 这是花费最高代价、效率差但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读以外,还避免了幻象读。
a、原子性 (atomicity): 一个事务中全部对数据库的操做是一个不可分割的操做序列,要么全作要么全不作。
b、一致性 (consistency): 事务的执行的先后数据的完整性保持一致.
c、隔离性 (isolation): 一个事务执行的过程当中,不该该受到其余事务的干扰
d、持久性(durability) : 一个事物一旦提交,它对数据库的改变就是永久的
a、Propagation.REQUIRED (默认) 面试必须说出来这个。
调用方已经存在事务,则加入到同一个事务中运行,不然,自启一个事务
b、Propagation.REQUIRES_NEW
不管什么时候自身都会开启新事务
c、Propagation.SUPPORTS
调用方存在事务,则加入到同一个事务中运行,若不存在事务,则以非事务的方式运行
d、Propagation.NOT_SUPPORTED
调用方存在事务,则会被挂起,直到被调用方运行完毕后,事务恢复。
e、Propagation.MANDATORY
调用方存在事务,则加入到同一个事务中运行,若不存在,则抛出异常
f、Propagation.NEVER
调用方存在事务,则抛出异常
g、Propagation.NESTED
若调用方存在事务,则运行一个嵌套事务,若调用方不存在事务,则以Propagation.REQUIRED的方式运行,即开启一个新的事务
实例化、初始化、使用、销毁。
静态变量:声明为 static 的静态变量实质上就是全局变量,这个静态变量只加载一次,只分配一块储存空间,该类全部实例变量共用同一个 static 变量
静态方法: 声明为static的静态方法有如下几个特色:
(1)静态方法只能调用静态方法;
(2)静态方法只能访问静态数据;
(3)静态方法不能以任何方式引用this或super
静态类:一般一个普通类不容许声明为静态,只有一个内部类才能够(main方法就是一个典型),这时这个声明的静态类能够直接做为一个普通类来使用,而不须要实例一个外部类。
变量:final修饰的变量的值不能被修改,是一个常量
方法:final修饰的方法不能被重写
类:final修饰的类不能被继承
(1)、间接实例化方式不一样(抽象类和接口都不能直接实例化)
实例化时,抽象类变量必须指向实现全部抽象方法的子类对象
实例化时,接口变量必须指向实现全部接口方法的类对象
(2)、继承对象不一样
抽象类要被子类继承
接口要被类实现。
(3)、是否有方法实现不一样
接口只能作方法声明,不能有方法实现
抽象类中能够作方法声明,也能够作方法实现
(4)、变量
接口里定义的变量只能是公共的静态的常量
抽象类中的变量是普通变量
其余:抽象方法只能申明,不能实现。abstract void abc();不能写成abstract void abc(){}。
抽象类里能够没有抽象方法 。
若是一个类里有抽象方法,那么这个类只能是抽象类 。
抽象方法要被实现,因此不能是静态的,也不能是私有的。
接口可继承接口,并可多继承接口,但类只能单根继承。
(1) 能访问除构造方法之外全部的属性、方法,经过this.来调用方法和属性
(2) 不能够在静态方法中使用
(3) 在构造方法中使用this(参数列表) 调用本类的其它构造方法,必须放在构造方法的第一句。
(1) 访问父类的方法和属性;
(2) 在构造方法中经过 super(参数列表) 来调用父类的构造方法,必须放在子类构造方法里的第一行。
final:修饰符(关键字)有三种用法:
(1)类:若是一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承。
(2)变量:将变量声明为final,能够保证它们在使用中不被改变,被声明为final 的变量在初始化之后的引用中只能读取不可修改。
(3)方法:被声明为 final 的方法也一样只能使用,不能在子类中被重写。
finally:一般放在try…catch的后面构造老是执行代码块,这就意味着程序不管正常执行仍是发生异常,这里的代码只要JVM不关闭都能执行,能够将释放外部资源的代码写在finally块中。
finalize:Object类中定义的方法,Java中容许使用finalize() 方法在垃圾收集器将对象从内存中清除出去以前作必要的清理工做。这个方法是由垃圾收集器在销毁对象时调用的,经过重写finalize() 方法能够整理系统资源或者执行其余清理工做。
Error 表示系统级的错误和程序没必要处理的异常,是恢复不是不可能但很困难的状况下的一种严重问题;好比内存溢出,不可能期望程序能处理这样的状况;
Exception 表示须要捕捉或者须要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示若是程序运行正常,从不会发生的状况。
MVC是Model—View—Controler的简称。即模型—视图—控制器。MVC是一种设计模式,它强制性的把应用程序的输入、处理和输出分开。
MVC中的模型、视图、控制器它们分别担负着不一样的任务。
模型: 模型表示业务数据和业务处理,至关于JavaBean。一个模型能为多个视图提供数据。这提升了应用程序的重用性。
视图: 视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并接受用户的输入。视图不进行任何业务逻辑处理。
控制器: 当用户单击Web页面中的提交按钮时,控制器接受请求并调用相应的模型去处理请求,而后根据处理的结果调用相应的视图来显示处理的结果。
MVC的处理过程:首先控制器接受用户的请求,调用相应的模型来进行业务处理,并返回数据给控制器。控制器调用相应的视图来显示处理的结果。并经过视图呈现给用户。
①JDBC编程流程固定,同时将sql语句和java代码混在了一块儿,常常须要拼凑sql语句,细节很繁琐;
②ibatis(mybatis)它不彻底是一个ORM框架,由于MyBatis须要程序员本身编写Sql语句,不过mybatis能够经过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。可是mybatis没法作到数据库无关性,若是须要实现支持多种数据库的软件则须要自定义多套sql映射文件,工做量大。
③Hibernate对象/关系映射能力强,数据库无关性好,由于hibernate自动生成sql语句,咱们没法控制该语句,咱们就没法去写特定的高效率的sql。对于一些不太复杂的sql查询,hibernate能够很好帮咱们完成,可是,对于特别复杂的查询,hibernate就很难适应了,这时候用ibatis就是不错的选择,由于ibatis仍是由咱们本身写sql语句。
(1)Connection提供了事务处理的方法,经过调用setAutoCommit(false)能够设置手动提交事务;
(2)当事务完成后用commit()显式提交事务;
(3)若是在事务处理过程当中发生异常则经过rollback()进行事务回滚。
(4)除此以外,从JDBC 3.0中还引入了Savepoint(保存点)的概念,容许经过代码设置保存点并让
事务回滚到指定的保存点。