鲁迅说:去年没考,今年一定考,不信我们赌台面包机。
简单选择排序:对于一组给定的一组记录,经过第一轮比较后等到最小的记录,然后将记录与第一个记录的位置进行交换,接着对不包括第一个记录的其他记录进行第二轮比较,得到最小的记录并与第二个记录进行位置交换;重复过程,直到进行比较的记录只有一个为止。
public static int[] Sort(int[] arr) {
for(int i = 0; i < arr.length - 1; i++) {
for(int j = i + 1; j < arr.length; j++) {
if(arr[j] < arr[i]) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
return arr;
}
直接插入排序:对于给定一组记录,初始化的时候假设第一个记录自成一个有序序列,其余记录均为无序序列。接着从第二个记录开始依次将当前处理的记录与前面的有序序列进行比较后插入到前面的有序序列中,直到最后一个记录插入到有序序列中为止。
public static int[] Sort(int[] arr) {
for(int i = 1; i < arr.length; i++) {
for(int j = 0; j < i; j++) {
if(arr[i] < arr[j]) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
return arr;
}
冒泡排序:顾名思义就是整个过程就像泡泡一样上升,单向冒泡排序的基本思想是(假设从小到大),对于给定的n个记录,从第一个记录开始依次对相邻的两个记录进行比较,当前面的记录大于后面的记录时,交换位置,进行一轮比较和交换后,n个记录中最大的记录将位于第n位;然后对前面的(n-1)个记录进行第二轮比较,重复该过程直到进行比较的记录只剩一个为止。
public static int[] Sort(int[] arr) {
for(int i = 0; i < arr.length - 1; i++) {
for(int j = 0; j < arr.length - 1 - i; j++) {
if(arr[j] > arr[j + 1]) {
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
System.out.println("第" + i + "趟:" + Arrays.toString(arr));
}
return arr;
}
快速排序:是一种非常高效地排序算法,它采用"分而治之"的思想,把大的拆分成小的,小的再拆分成更小的。
public static int[] quickSort(int[] arr, int low, int high) {
int l = low;
int h = high;
int base = arr[low];
while(l < h) {
while(l < h && arr[h] >= base) {
h --;
}
arr[l] = arr[h];
while(l < h && arr[l] <= base) {
l ++;
}
arr[h] = arr[l];
}
arr[l] = base;
System.out.println(Arrays.toString(arr));
if(l - 1 > low) {
quickSort(arr,low,l - 1);
}
if(h + 1 < high) {
quickSort(arr, h + 1, high);
}
return arr;
}
单例模式:是一种对象创建型模式,使用单例模式,可以保证一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。其实,GOF对单例模式的定义是:保证一个类只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
饿汉式:所谓饿汉模式就是立即加载,一般情况下再调用getInstance()方法之前就已经产生了实例,也就是在类加载的时候已经产生了。适用于多线程,但这种模式的缺点很明显,就是当单例类很大的时候很占用资源,没有使用该类的时候也会创建该类的实例。因此这种方式适合占用资源少,在初始化的时候就被用到的类。
//持有私有静态变量,防止被引用
private static final SingleTonHungary singleTon = new SingleTonHungary();
//构造方法私有化,防止被实例化
private SingleTonHungary() {
}
//提供全局的静态访问方法
public static SingleTonHungary getInstance() {
try {
Thread.sleep(1000);//模拟在创建对象时做的一些准备
}catch (Exception e) {
e.printStackTrace();
}
return singleTon;
}
懒汉式:懒汉模式就是延迟加载,也叫懒加载。在程序中需要用到的时候再创建实例,这样保证内存不会浪费。针对懒汉模式,直接通过设置同步代码块,使用双重检查锁机制,可以成功的解决线程不安全和效率问题,这也是大多数多线程结合单例模式使用的解决方案。
//持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载
//添加volatile关键字,保证内存的可见性,所有线程都会去主存中取数据而不是在线程的缓存中取数据,保证了数据的更新能实时对任何线程可见
private volatile static SingleTonLazy singleTon = null;
//构造方法私有化,防止被实例化
private SingleTonLazy() {
}
//提供全局的静态访问方法,创建实例,只对第一次创建这个对象的时候上锁,这样效果更好
public static SingleTonLazy getInstance() {
try {
if(null == singleTon) {
Thread.sleep(1000);//模拟在创建对象时做的一些准备
synchronized (SingleTonLazy.class) {
if(null == singleTon) {
singleTon = new SingleTonLazy();
}
}
}
}catch (Exception e) {
e.printStackTrace();
}
return singleTon;
}
静态私有内部类:可以看到这种方式没有显示的进行任何同步操作,如何保证线程安全呢?和饿汉式一样,是靠JVM保证类的静态成员只能被加载一次的特点,这样就从JVM的层面保证了只会有一个对象。在加载一个类时,其内部类不会同时被加载。一个类被加载,当且仅当其某个静态成员(静态域,构造器,静态方法等)被调用时发生。可以说这种方式时实现单例模式的最优解。
private SingletonStaticInner() {
}
private static class SingletonInner {
private static SingletonStaticInner singleTon = new SingletonStaticInner();
}
public static SingletonStaticInner getInstance() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return SingletonInner.singleTon;
}
静态代码块:可以说就是一种饿汉方式。
private static SingletonStaticBlock singleTon = null;
private SingletonStaticBlock() {
}
static {
singleTon = new SingletonStaticBlock();
}
public static SingletonStaticBlock getInstance() {
return singleTon;
}
工厂模式
工厂方法模式:属于类的创建型模式,又被称为多态工厂方法模式,工厂方法模式的意义是定义一个创建一个产品对象的接口,将实际创建工作推迟到子类中,核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色仅仅只负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使在不修改具体工厂角色的情况下引进新的产品,这样解决了简单工厂模式扩展性不好的问题。
模式中包含的角色及其职责:
具体角色:工厂方法模式所创建的具体实例化对象
场景:对mysql/orcale数据库中的User表进行操作
//定义User类
public class User {
private int uid;
private String name;
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//定义一个对User表操作的接口
public interface IUserOpertion {
public void insert(User user);
public User getUser(int uid);
}
//定义mysql对User表操作的类
public class MysqlUserOpertion implements IUserOpertion {
@Override
public void insert(User user) {
System.out.println("在mysql中的user表中插入一条元素");
}
@Override
public User getUser(int uid) {
System.out.println("在mysql中的user表得到id为"+uid+"的一条数据");
return null;
}
}
//定义orcale对User表操作的类
public class OrcaleUserOpertion implements IUserOpertion {
@Override
public void insert(User user) {
System.out.println("在oracle中的user表中插入一条元素");
}
@Override
public User getUser(int uid) {
System.out.println("在oracle中的user表得到id为"+uid+"的一条数据");
return null;
}
}
//定义一个工厂接口,用来编写生产访问User表的对象的接口
public interface ISqlFactory {
public IUserOpertion createUserOpertion();
}
//定义生产mysqlUserOpertion对象的mysql工厂类
public class MysqlFactory implements ISqlFactory {
@Override
public IUserOpertion createUserOpertion() {
return new MysqlUserOpertion();
}
}
//定义生产orcaleUserOpertion对象的orcale工厂类
public class OrcaleFactory implements ISqlFactory {
@Override
public IUserOpertion createUserOpertion() {
return new OrcaleUserOpertion();
}
}
//定义一个用户测试类
public class TestFactory {
public static void main(String[] args) {
ISqlFactory sqlFactory = new MysqlFactory();
IUserOpertion userOpertion = sqlFactory.createUserOpertion();
userOpertion.insert(new User());
userOpertion.getUser(0);
}
}
//返回结果
在mysql中的user表中插入一条元素
在mysql中的user表得到id为0的一条数据
抽象工厂模式:是所有形态的工厂模式中最为抽象和最具一般性的模式,抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。
模式中包含的角色及其职责:
场景:在上面的基础上增加一张Login表,同样是在mysql和orcale中进行操作
//定义Login类
public class Login {
private int id;
private Date date;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
//定义一个对Login表操作的接口
public interface ILoginOpertion {
public void insert(Login login);
public Login getLogin(int id);
}
//定义mysql对Login表操作的类
public class MysqlLoginOpertion implements ILoginOpertion {
@Override
public void insert(Login login) {
System.out.println("对 MySQL 里的 Login 表插入了一条数据");
}
@Override
public Login getLogin(int id) {
System.out.println("通过 id 在 MySQL 里的 Login 表得到了一条数据");
return null;
}
}
//定义orcale对Login表操作的类
public class OrcaleLoginOpertion implements ILoginOpertion {
@Override
public void insert(Login login) {
System.out.println("对 Oracle 里的 Login 表插入了一条数据");
}
@Override
public Login getLogin(int id) {
System.out.println("通过 uid 在 Oracle 里的 Login 表得到了一条数据");
return null;
}
}
//修改工厂接口,增加对Login表操作的接口
public interface ISqlFactory {
public IUserOpertion createUserOpertion();
public ILoginOpertion createLoginOpertion();
}
//修改mysql工厂,生产对Login表操作的类
public class MysqlFactory implements ISqlFactory {
@Override
public IUserOpertion createUserOpertion() {
return new MysqlUserOpertion();
}
@Override
public ILoginOpertion createLoginOpertion() {
return new MysqlLoginOpertion();
}
}
//修改orcale工厂,生产对Login表操作的类
public class OrcaleFactory implements ISqlFactory {
@Override
public IUserOpertion createUserOpertion() {
return new OrcaleUserOpertion();
}
@Override
public ILoginOpertion createLoginOpertion() {
return new OrcaleLoginOpertion();
}
}
//定义一个用户测试类
public class TestFactory {
public static void main(String[] args) {
ISqlFactory sqlFactory = new MysqlFactory();
IUserOpertion userOpertion = sqlFactory.createUserOpertion();
userOpertion.insert(new User());
userOpertion.getUser(0);
ILoginOpertion loginOpertion = sqlFactory.createLoginOpertion();
loginOpertion.insert(new Login());
loginOpertion.getLogin(0);
}
}
//返回结果
在mysql中的user表中插入一条元素
在mysql中的user表得到id为0的一条数据
对 MySQL 里的 Login 表插入了一条数据
通过 id 在 MySQL 里的 Login 表得到了一条数据
抽象工厂模式与工厂方法模式的区别:比如说有两个工厂分别生产鼠标与键盘,如果用工厂方法模式,替换生产键盘的工厂方法,就可以把键盘从罗技换到微软;如果用抽象工厂方法模式,只需要换家工厂,就可以替换鼠标与键盘一起。如果产品有10几种,当然用抽象工厂模式一次替换最方便。所以说,抽象工厂就像一家工厂,而工厂方法模式就像是工厂的一种产品生产线。
23种设计模式,分为三大类:
已知:一个HashMap
分析:集合排序可以使用Collections类中的sort()方法进行排序,因为HashMap集合存储无序,而它的子类LinkedHashMap是存储有序的,看似返回HashMap类型,实则利用多态返回是它的子类LinkedHashMap类型。
public class User {
private String name;
private int age;
public User() {
}
public User(String name,int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
public class Test {
public static void main(String[] args) {
HashMap<Integer, User> map = new HashMap<Integer, User>();
map.put(1, new User("张三",18));
map.put(2, new User("李四",19));
map.put(3, new User("王五",20));
map = sortHashMap(map);
Set<Entry<Integer, User>> entrySet = map.entrySet();
for (Entry<Integer, User> entry : entrySet) {
System.out.println(entry.getKey() + " " + entry.getValue().toString());
}
}
public static HashMap<Integer, User> sortHashMap(HashMap<Integer, User> map){
Set<Entry<Integer, User>> entrySet = map.entrySet();
List<Entry<Integer, User>> list = new ArrayList<Entry<Integer, User>>(entrySet);
Collections.sort(list, new Comparator<Entry<Integer, User>>() {
@Override
public int compare(Entry<Integer, User> o1, Entry<Integer, User> o2) {
return o2.getValue().getAge() - o1.getValue().getAge();
}
});
HashMap<Integer, User> sortHashMap = new LinkedHashMap<Integer, User>();
for (Entry<Integer, User> entry : list) {
sortHashMap.put(entry.getKey(), entry.getValue());
}
return sortHashMap;
}
}
局部代码块:定义在方法或语句中
构造代码块:定义在类中成员位置
静态代码块:定义在类中成员位置,使用static修饰的代码块
创建类的实例,也就是new一个对象
访问某个类或接口的静态变量,或者对该静态变量赋值
调用该类的静态方法
反射
初始化一个类的子类,会首先初始化该子类的父类
JVM启动时标明的启动类,即文件名和类名相同的类
用户发送请求至前端控制器
前端控制器收到请求调用处理器映射器
处理器映射器根据请求url找到具体的处理器,生成处理器对象以及处理器拦截器(如果有则生成)一并返回给前端控制器
前端控制器通过处理器适配器调用处理器
执行处理器(Controller,也叫后端控制器)
处理器执行完成后返回ModelAndView
处理器适配器将处理器执行结果ModelAndView返回给前端控制器
前端控制器将ModelAndView传给视图解析器
视图解析器解析后返回具体View
前端控制器对View进行渲染视图(即将模型数据填充至视图中)
前端控制器响应用户
<!-- 直接配置注解式处理器引射器和处理器适配器比较麻烦,所以在springmvc.xml中使用注解驱动来加载 -->
<mvc:annotation-driven />
<!-- 视图解析器使用SpringMVC框架默认的InternalResourceViewResolver,支持JSP视图解析 -->
<!-- 最终jsp物理地址:前缀+逻辑视图名+后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
//在使用注解前需要先配置web.xml,springmvc.xml文件
<!-- web.xml文件 -->
<!-- springmvc的前端控制器 -->
<servlet>
<servlet-name>e3-manager-web</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配 置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>e3-manager-web</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- springmvc.xml文件 -->
<!-- spring将自动扫描指定包及其子包下标注了@Component,@Repository,@Service,@Controller注解的类,将其变成由spring管理的bean。多个包之间用,分隔 -->
<!-- 注解需要开启对应的解析器,比如依赖注入的时候使用注解就必须开启<context:annotation-config/>,但是此配置就已经默认开启了解析器 -->
<context:component-scan base-package="cn.e3mall.controller" />
@Component,@Repository,@Service,@Controller:该四种注解都是注解在类上,被注解的类将被spring初始化为一个bean,将由spring统一管理。
@RequestMapping:用于处理请求地址映射,可以作用在类和方法上。在class上添加则指定通用请求前缀,限制此类下所有方法的请求url必须以请求前缀开头。
@RequestParam:用于将请求参数区数据映射到功能处理方法的参数上。
@PathVariable:可以根据value获取请求路径上相对应的值。
@RequestBody:用于读取http请求的json数据,将json数据转换为java对象并绑定到Controller方法的参数上。
@ResponseBody:实现将Controller方法返回java对象转换为json响应给客户端,即Controller方法返回字符串不经过视图解析器。
@Value:给bean中的属性赋默认值。
@Autowried:自动注入,默认按类型装配依赖对象,默认情况下它要求对象必须存在,如果允许null值,可以设置它的required属性为false,如果有多个类型一样的bean候选者-即一个接口或父类有多个实现类或者子类可以为其注入,则需要结合@Qualifier注解一起使用,就可以按名称进行装配。
@Resource:默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找;如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:resource/resource.properties"/>
#resource.properties中内容
#图片上传服务器地址
IMAGE_SERVER_URL=http://192.168.25.133/
//controller中使用@value注解读取配置文件中键所对应的值赋给该属性
@Value("${IMAGE_SERVER_URL}")
private String IMAGE_SERVER_URL;
select 字段名1,字段名2,... from A表 a
left join B表 b on A.bid = b.id
where 条件1 and 条件2
group by 字段n having 条件n
order by 字段n (desc)
limit 记录数;
/*创建部门表*/
CREATE TABLE dept(
deptno INT PRIMARY KEY,
dname VARCHAR(50),
loc VARCHAR(50)
);
/*创建雇员表*/
CREATE TABLE emp(
empno INT PRIMARY KEY,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
COMM DECIMAL(7,2),
deptno INT,
CONSTRAINT fk_emp FOREIGN KEY(mgr) REFERENCES emp(empno)
);
/*创建工资等级表*/
CREATE TABLE salgrade(
grade INT PRIMARY KEY,
losal INT,
hisal INT
);
/*创建学生表*/
CREATE TABLE stu(
sid INT PRIMARY KEY,
sname VARCHAR(50),
age INT,
gander VARCHAR(10),
province VARCHAR(50),
tuition INT
);
#查出至少有一个员工的部门。显示部门编号、部门名称、部门位置、部门人数。
select d.deptno,d.dname,d.loc,count(e.deptno) from dept d
left join emp e on e.deptno = d.deptno
group by e.deptno having count(e.deptno) >= 1;
select d.deptno,d.name,d.loc,z.cnt from dept d
inner join (select deptno,count(*) cnt from emp group by deptno) z
on d.deptno = e.deptno;
#列出薪金比关羽高的所有员工。
select * from emp e
where e.sal > (select sal from emp where ename = '关羽') order by e.sal desc;
#列出所有员工的姓名及其直接上级的姓名。
select e.ename,z.ename from emp e left join emp z on e.mgr = z.empno;
#列出受雇日期早于直接上级的所有员工的编号、姓名、上级姓名、受雇日期、上级受雇日期、部门名称。
select e.empno,e.ename,m.ename,e.hiredate,m.hiredate,d.dname from emp e
inner join emp m on e.mgr = m.empno
inner join dept d on e.deptno = d.deptno
where e.hiredate < m.hiredate;
#列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门。
select d.dname,e.* from dept d left join emp e on d.deptno = e.deptno;
#列出所有文员的姓名及其部门名称,部门的人数。
select e.ename,d.dname,m.cnt from emp e
left join dept d on e.deptno = d.deptno
left join (select deptno,count(*) cnt from emp group by deptno) m on e.deptno = m.deptno
where e.job = '文员';
#列出最低薪金大于15000的各种工作及从事此工作的员工人数。
#即什么工作的最低工资大于15000,统计其人数
select job,count(*) from emp group by job having min(sal) > 15000;
#列出在销售部工作的员工的姓名,假定不知道销售部的部门编号。
select e.ename from emp e
where e.deptno = (select deptno from dept where dname = '销售部');
#列出薪金高于公司平均薪金的所有员工信息,所在部门名称,上级领导,工资等级。
select e.*,d.dname,m.ename,s.grade from emp e
left join dept d on d.deptno = e.deptno
left join emp m on e.mgr = m.empno
left join salgrade s on e.sal between s.losal and s.hisal
where e.sal > (select avg(sal) from emp) order by sal desc;
#列出与庞统从事相同工作的所有员工及部门名称。
select e.*,d.dname from emp e
left join dept d on e.deptno = d.deptno
where e.job = (select job from emp where ename = '庞统');
#列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金、部门名称。
select e.ename,e.sal,d.dname from emp e
left join dept d on d.deptno = e.deptno
where e.sal > (select max(sal) from emp group by deptno having deptno = 30)
order by e.sal desc;
#列出每个部门的员工数量、平均工资。
select d.dname,e.avg,e.cnt from dept d
left join (select avg(sal) avg,count(*) cnt,deptno from emp group by deptno) e on d.deptno = e.deptno;