归并排序
归并排序是通过合并多个有序序列的排序方法,是运用分支法的典型范例。
主要步骤
划分:将待排序的序列划分为大小大致相等的两个子序列。
治理:当子序列的规模大于1时,递归排序子序列,如果子序列规模为1则称为有序序列。
组合:将两个有序序列合并为一个有序序列。
HashMap和HashTable之间的区别
HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。HashMap的底层结构是一个数组,数组中的每一项是一条链表。
HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
HashMap不能保证随着时间的推移Map中的元素次序是不变的。
1、父类不同:
HashMap是继承自AbstractMap类,而HashTable是继承自Dictionary(已被废弃,详情看源代码)。不过它们都实现了同时实现了map、Cloneable(可复制)、Serializable(可序列化)这三个接口。
Hashtable比HashMap多提供了elments() 和contains() 两个方法。
elments() 方法继承自Hashtable的父类Dictionnary。elements() 方法用于返回此Hashtable中的value的枚举。
contains()方法判断该Hashtable是否包含传入的value。它的作用与containsValue()一致。事实上,contansValue() 就只是调用了一下contains() 方法。
2、null值问题
Hashtable既不支持Null key也不支持Null value。Hashtable的put()方法的注释中有说明 。
HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
3、线程安全性
Hashtable是线程安全的,它的每个方法中都加入了Synchronize方法。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步
HashMap不是线程安全的,在多线程并发的环境下,可能会产生死锁等问题。具体的原因在下一篇文章中会详细进行分析。使用HashMap时就必须要自己增加同步处理,
虽然HashMap不是线程安全的,但是它的效率会比Hashtable要好很多。这样设计是合理的。在我们的日常使用当中,大部分时间是单线程操作的。HashMap把这部分操作解放出来了。当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。
tip:HashMap是JDk1.2之后有的,而在JDK1.5中,伟大的Doug Lea给我们带来了concurrent包,从此Map也有安全的了。也就就是有了ConcurrentHashMap(关于这个的理解下次有机会再写,或自行百度)
4、遍历方式不同
Hashtable、HashMap都使用了Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
HashMap的Iterator是fail-fast迭代器。当有其它线程改变了HashMap的结构(增加,删除,修改元素),将会抛出ConcurrentModificationException。不过,通过Iterator的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。
JDK8之前的版本中,Hashtable是没有fast-fail机制的。在JDK8及以后的版本中 ,Hashtable也是使用fast-fail的。(此处可以去看一下1.5和1.8JDK源码的对比)
5、初始容量不同
Hashtable的初始长度是11,之后每次扩充容量变为之前的2n+1(n为上一次的长度)
而HashMap的初始长度为16,之后每次扩充变为原来的两倍
创建时,如果给定了容量初始值,那么Hashtable会直接使用你给定的大小,而HashMap会将其扩充为2的幂次方大小。
6、计算哈希值的方法不同
为了得到元素的位置,首先需要根据元素的 KEY计算出一个hash值,然后再用这个hash值来计算得到最终的位置
Hashtable直接使用对象的hashCode。hashCode是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值。然后再使用除留余数发来获得最终的位置。 然而除法运算是非常耗费时间的。效率很低
HashMap为了提高计算效率,将哈希表的大小固定为了2的幂,这样在取模预算时,不需要做除法,只需要做位运算。位运算比除法的效率要高很多.
迭代器模式
迭代器模式:提供一种方法顺序访问一个集合对象中的各个元素,而又不需要暴漏对象的内部表示。
合理组织数据的结构以及相关操作时程序设计的一个重要方面,比如在程序设计中经常会使用诸如链表、散列表等数据结构。链表和散列表等数据结构都是可以存放若干个对象的集合,其区别时按着不同的方式来存储对象。我们希望无论何种集合,应当允许程序以一种统一的方式遍历集合中的对象,而不需要知道这些对象在集合中时如何表示存储的。
迭代器模式是遍历集合的一种成熟模式,迭代器模式的关键是将遍历集合的任务交给一个称作迭代器的对象。
包含角色:
1、集合(Aggregate):一个接口,规定了集合需要实现的操作。
2、具体集合(ConcreteArrregate):具体集合是实现集合接口的类的实例,具体集合按着一定的结构存储对象,具体集合应当有一个方法,该方法返回一个针对该集合的具体迭代器。
3、迭代器(Iterator): 一个接口,规定了遍历具体集合的方法,比如next()方法。
4、具体迭代器(ConcreteIterator): 实现集合接口的类的实例。具体迭代器在实现迭代器 接口所规定的遍历集合的方法时,比如next()方法,要保证next()方法的首次调用将按着集合 的数据结构找到该集合中的一个对象,而且每当找到集合中的一个对象,立刻根据该集合的存储结构得到待遍历的后继对象的引用,并保证依次调用next()方法可以遍历集合。
优点:
1、用户使用迭代器访问集合中的对象,而不需要知道这些对象在集合中时如何表示以及存储的。
2、用户可以同时使用多个迭代器遍历一个集合。
适用情景:
1、让用户访问一个集合中的对象,但不想暴露对象在集合中的存储结构。
2、希望对遍历不同的集合提供一个统一的接口。
简单的例子:现在有若干个学生,有姓名、学号和出生日期等属性。
(1) 使用链表存放学生对象。
(2) 用一个散列表和一个树集存放链表中的对象。
(3) 使用散列表查询某个学生。
DDL、DML、DQL、DCL、TCL语句的概念与区别
DDL(Data Definition Language,数据定义语言):
用于描述数据库中要存储的现实世界实体的语言。
数据定义语言DDL用来创建数据库中的各种对象-----表、视图、索引、同义词、聚簇等,如:
create table/view/index/syn/cluster
DDL操作是隐性提交的!不能rollback 。
常见DDL操作:
show databases; 显示所有数据库
use 数据库名; 使用该数据库
show create database 数据库名; 显示创建该数据库的SQL语句
create database 数据库名; 创建数据库
create database 数据库名 character set utf8; 创建指定字符编码的数据库
drop databse 数据库名; 删除数据库
create table 表名(id int ,name char(10),age int ); 创建表
show tables; 显示所有表
show create table 表名; 显示创建该表的SQL语句
alter table 表名 add id int ; 表中新增列
alter table 表名 modify id double; 修改表中列的属性
alter table 表名 change id id2 int; 修改表中列的名字和属性
alter table 表名 drop id; 删除表中的列
rename table 表名 to 新表名; 修改表格的名字
alter table 表名 character set utf8; 修改表的字符编码格式
DML( Data Manipulation Language,数据操纵语言):
使用户能够查询数据库以及操作已有数据库中的数据的计算机语言。
数据操纵语言DML主要有三种形式:
插入:insert
更新:update
删除:delete
常见DML操作:
insert into 表名 (字段1,字段2,字段3) values (值1,值2,值3) 新增值到表中
update 表名 set name = ‘xx’ where id =3; 更新表中数据
delete from 表名 where id = 2; 删除表中的数据
DQL(Data Query Language SELECT,数据查询语言):
主要用来查看表中的数据,也是平时使用最多的操作。
数据查询语言DQL基本结构是由SELECT子句,FROM子句,WHERE子句组成的查询块:
select <字段名表> from <表或视图名> where <查询条件>
常见DQL操作:
select * from 表名 where id =3; 查询表中数据
select * from 表名 order by id desc | asc; 排序查询
select * from 表名 group by 字段; 分组查询
select * from 表名 where name like ‘%aa%’; 模糊查询
select * from 表名 limit (2,5); 分页查询
select * from 表名 where age between 20 and 30; 范围查询
select * from 表名 where id in (1,3,5); 部分查询
DCL(Data Control Language,数据控制语言):
用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果。如:
grant:授权;
revoke:取消权限;
常见DCL操作:
给用户jerry授予对test_db数据库的增删改查权限,允许该用户从IP为’192.168.0.10’的网络登录:
GRANT INSERT,SELECT,UPDATE,DELETE ON test_db.* TO ‘jerry’@‘192.168.0.10’ IDENTIFIED BY ‘password’ WITH GRANT OPTION;或
CREATE USER ‘jerry’@‘192.168.0.10’ IDENTIFIED BY ‘password’;
GRANT INSERT,SELECT,UPDATE,DELETE ON test_db.* TO ‘jerry’@‘192.168.0.10’;
收回用户对test_db库的删除权限:
REVOKE DELETE ON test_db.* FROM ‘jerry’@‘192.168.0.10’;
查询给’jerry’@'192.168.0.10’所授予的所有权限:
SHOW GRANTS FOR ‘jerry’@‘192.168.0.10’;
TCL(Transaction Control Language,事物控制语言):
用来对事务进行管理。 如:
COMMIT : 保存已完成事务动作结果
SAVEPOINT : 保存事务相关数据和状态用以可能的回滚操作
ROLLBACK : 恢复事务相关数据至上一次COMMIT操作之后
SET TRANSACTION : 设置事务选项
DML语句对表数据进行操作的时候都会加上行级锁,确认完成后,必须加上事物处理结束的命令COMMIT才能正式生效,否则改变不一定写入数据库里。如果想撤回这些操作, 可以用命令 ROLLBACK 复原。
注意:
在运行INSERT,DELETE和UPDATE语句前最好估算一下可能操作的记录范围,应该把它限定在较小范围内,例如一万条记录,否则ORACLE处理这个事物用到很大的回退段。程序响应慢甚至失去响应。如果记录数上十万以上这些操作。可以把这些SQL语句分段分次完成。其间加上COMMIT确认事物处理。
数据的提交:
在数据库的插入、删除和修改操作时,只有当事务在提交到数据库时才算完成。在事务提交前,只有操作数据库的这个人才能有权看到所做的事情,别人只有在最后提交完成后才可以看到。提交数据有三种类型:显式提交、隐式提交及自动提交。
1、显式提交
用COMMIT命令直接完成的提交为显式提交。其格式为:
SQL>COMMIT;
2、隐式提交
用SQL命令间接完成的提交为隐式提交。这些命令是:
ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。
3、自动提交
若把AUTOCOMMIT设置为ON,则在插入、修改、删除语句执行后,系统将自动进行提交,这就是自动提交。其格式为:
SQL>SET AUTOCOMMIT ON;