Stream流

Stream流是一个来自数据源的元素队列
获取流的方法:

  • 通过Collection
  • 通过静态方法Stream.of

常用方法:

//ForEach, void forEach(Consumer<? super T> action);
public static void main(String[] args){
    Stream<String> stream = Stream.of("A","B","C","D");
    stream.forEach(System.out::println);
}
//filter, Stream<T> filter<Predicate<? super T> predicate);
public static void main(String[] args){
    Stream<String> stream = Stream.of("Aaa","Bb","Ccc","Dddd");
    Stream<String> stream1 = stream.filter((String s) -> s.length() <= 2);
}
//<R> Stream<R> map(Function<?super T, ? extends R>mapper)
public static void main(String[] args){
    Stream<String> stream = Stream.of("1","2","3","4");
    Stream<Integer> stream2 = stream.map(Integer::parseInt);
}
//long count()
public static void main(String[] args){
    Stream<String> stream = Stream.of("Aaa","Bb","Ccc","Dddd");
    long count = stream.count();
}
//Stream<T> limit(long maxSize), Stream<T> skip(long n)
public static void main(String[] args){
    Stream<String> stream = Stream.of("Aaa","Bb","Ccc","Dddd");
    Stream<String> stream1 = stream.limit(3);
    Stream<String> stream2 = stream.skip(3);
}
//static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
public static void main(String[] args){
    Stream<String> stream1 = Stream.of("A","B","C","D");
    Stream<String> stream2 = Stream.of("E","F","G","H");
    Stream<String> concat = Stream.concat(stream1, stream2);
}

方法引用

引用的对象存在、引用的方法也已经存在

Junit

  1. 定义一个测试类 //建议命名为:CalculatorTest 包:cn.hitomi.test
  2. 测试方法:可以独立运行 //建议命名为:testAdd() 返回值建议void 参数建议为空
  3. 为方法加上@Test
  4. 使用断言Assert
  5. 申请IO等操作可以使用@Before预先执行,@After末尾执行

反射

将类的各个组成部分封装成其他对象
获取Class对象的方式:

  1. Class.forName("全类名") //多用于配置文件爱你
  2. 类名.class:通过类名的属性Class获取 //多用于参数传递
  3. 对象.getClass:在Object类中 //多用对对象获取字节码
    同一个字节码文件*.class 在一次程序运行过程中,只会被加载一次,无论是通过什么方法获取的

Class对象功能:
1.1 获取所有Public修饰的成员变量 Field[] getFields()
获取所有的成员变量 Field[] getDeclaredFields()
1.2 忽略修饰符的安全检查 setAccessible(true) //暴力反射
2.1 获取构造方法同理,getConstructor/getDeclaredConstructor
3.1 获取成员方法同理,getMethods/getDeclaredMethods

e.g. 通过配置文件加载指定类
File:src/pro.properties

className=domain.Person
methodName=eat

类Person中含有一个eat()的方法
Code4-1 Class ReflectDemo

public static void main(String[] args) throws IOException, ReflectiveOperationException {
    //load properties
    Properties pro = new Properties();
    //find the path of properties, using the Classloader
    pro.load(ReflectDemo.class.getClassLoader().getResourceAsStream("pro.properties"));
    //read the data in file
    String className = pro.getProperty("className");
    String methodName = pro.getProperty("methodName");
    //load the data into memory
    Class cls = Class.forName(className);
    //create Object
    Object obj = cls.newInstance();
    Method method = cls.getMethod(methodName);
    method.invoke(obj);
}

注解

@Override:检查是否继承父类
@Deprecated:检查是否过时
@SuppressWarnning:压制警告

自定义注解个格式:

元注解
public @interface 注解名称{}

通过javap反编译可以看到,其本质是是一个接口:
public interface MyAnno extends java.lang.annotation.Annotation {}
属性即接口中的抽象方法,对属性的返回值有要求(基本数据类型、String、枚举、注解)
如果定义了属性,在使用的时候需要给属性赋值,例如 @MyAnno(value = 12);如果只有一个属性,属性的名字可以忽略,另外可以在注解中使用default给属性赋初始值
元注解:
@Target:描述作用的位置 //ElementType:TYPE METHOD FIELD
@Retention:描述保留的阶段 //RUNTIME SOURCE CLASS
@Documented:是否抽取到api文档中
@Inherited:是否被子类继承
e.g. 使用注解重写Code4-1
Code4-2 @Interface pro

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Pro {
    String className();
    String methodName();
}

Code4-3 Class ReflectDemoAnno

@Pro(className = "domain.Person", methodName="eat")
public class ReflectDemoAnno {
    public static void main(String[] args) throws IOException, ReflectiveOperationException {
        //Resolve the annotation
        Class<ReflectDemoAnno> reflectDemoAnnoClass = ReflectDemoAnno.class;
        Pro annotation = reflectDemoAnnoClass.getAnnotation(Pro.class);
        String className = annotation.className();
        String methodName = annotation.methodName();
        Class cls = Class.forName(className);
        Object obj = cls.newInstance();
        Method method = cls.getMethod(methodName);
        method.invoke(obj);
    }

实际上就是在内存中生成了一个改注解接口的子类实现对象,然后获取指定注解,并调用注解中的抽象方法获取配置的属性值

e.g. 使用注解实现自动化测试
Code4-4 @Interface Check

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Check {
}

Code4-5 Class Calculator

public class Calculator {
    @Check
    public void add(){
        System.out.println("1 + 0 = " + (1+0));
    }
    @Check
    public void div(){
        System.out.println("1 / 0 = " + (1/0));
    }
}

Code4-6 Class TestCheck

public static void main(String[] args) throws IOException {
    Calculator c = new Calculator();
    Class cls = c.getClass();
    Method[] methods = cls.getMethods();
    int count = 0;
    BufferedWriter bw = new BufferedWriter(new FileWriter("bug.log"));
    for (Method method : methods) {
        if(method.isAnnotationPresent(Check.class)){
            try {
                method.invoke(c);
            } catch (Exception e) {
                count ++;
                bw.write(method.getName() +e.getCause().getClass().getSimpleName());
                bw.newLine();
                bw.write("----------");
                bw.newLine();
            }
        }
    }
    bw.write("Total Error is: " + count);
    bw.flush();
    bw.close();
}

数据库

优点:持久化存储、方便管理、使用统一的方式
SQL(Structured Query Language)
单行注释 -- 注释 或 # 注释
多行注释 /* 多行注释 */

  • DDL(数据定义语言):用于定义数据库对象、如create、drop、alter等
    CRUD(Create/Retrieve/Update/Delete)
show create database 数据库名称;
create database if not exists 数据库;
create database 数据库 character set gbk;
alter database 数据库 character set utf8;
drop database if exists 数据库;
select database();
use 数据库;
show tables;
desc 表;
create table 表(
    列1 数据类型1,
    列2 数据类型2,
         ...    
    列n 数据类型n
);
drop tables if exists 表;
create table 新表 like 旧表;
alter table 表名 rename to 新表名;
alter table 表名 character set utf8;
alter table 表名 add 列 数据类型;
alter table 表名 change 列 新列名 varchar(20);
alter table 表名 modify 列 varchar(10)>;
  • DML(数据操作语言):用于对数据库表中的对象进行修改,如insert、delete、update等
INSERT INTO 表名(列1,列2,...,列n) values(数据1,数据2,...,数据n);
INSERT INTO 表名 values(数据1,数据2,...,数据n);
DELETE FROM 表名 [WHERE 条件];
TRUNCATE TABLE 表名;//清空表
UPDATE 表名 SET 列1=值1, 列2=值2, ... , 列n=值n [WHERE 条件];
  • DQL(数据查询语言):用于查询数据库表中的记录,如select、where等
    基础查询
SELECT 字段 FROM 表 WHERE 条件 GROUP BY 分组 HAVING 分组后条件 ORDER BY 排序 LIMIT 分页;
SELECT DISTINCT 列 FROM 表;
SELECT a,b,a+b FROM d;
SELECT IFNULL(a,0) FROM b;
SELECT a+b AS new FROM c;

条件查询:

SELECT * FROM student WHERE age BETWEEN 20 AND 30;
SELECT * FROM student WHERE age IN (10,11,12);
//NULL值不可以用运算符去判断
SELECT * FROM student WHERE English IS NOT NULL;
「_」单个任意字符 「%」任意多个字符
SELECT * FROM student WHERE LIKE '张%';                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
  • DCL(数据控制语言)
排序
SELECT * FROM student ORDER BY math DESC, English DESC  //默认ASC
聚合 COUNT MAX MIN SUM AVG
SELECT COUNT(english) FROM student 
保证非空的方法:
SELECT COUNT(IFNULL(English,0)) FROM student;
SELECT COUNT(*) FROM student;
分组
SELECT sex, AVG(math) FROM student WHERE math > 70 GROUP BY sex HAVING COUNT(id)> 2 ;
分页
SELECT * FROM student LIMIT 0,3;   //(当前页码-1)*每页条数,每页条数/

约束
主键约束PRIMARY KEY、非空约束NOT NULL、唯一约束UNIQUE(不包括null)、外键约束FOREIGN KEY

创建时增加
CREATE TABLE stu(
    id INT,
    NAME VARCHAR(20) NOT NULL --非空约束
);
修改约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);
增加约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;
删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;
删除主键
ALTER TABLE stu DROP PRIMARY KEY;
自动增长 AUTO_INCREMENT
删除自动增长
ALTER TABLE stu MODIFY id INT;
创建时添加外键约束
CREATE TABLE employee(
    id INT PRIMARY KEY AUTOP_INCREMENT,
    NAME VARCHAR(20),
    age INT,
    dep_id INT,
    CONSTRANT emp_dep_fk FOREIGN KEY (dep_id) REFERENCES department(id)
);
删除外键约束
ALTER TABLE employee DROP FOREIGN KEY emp_dep_fk;
添加外键约束
ALTER TABLE employee ADD CONSTRAINT emp_dep_fk FOREIGN KEY (dep_id) REFERENCES department(id);
级联
ON UPDATE CASCADE;//更新
ON DELETE CASCADE;//删除

设计范式
表的关系:
一对一(A只有一个B,B只有一个A)
一对多(一个部门有多个员工,一个员工只能对应一个部门)
在n的一端建立外键指向1的一端的主键
多对多(一个学生可以选择课程,一个课程也可以被很多学生选择)
多对多关系借助第张表,第三张表至少包含两个字段,分别指向两张表的主键(联合主键)

e.g.成绩表

学号姓名系名系主任课程名称分数
10010Albert.B经济Charles.D高等数学95
10010Albert.B经济Charles.D大学英语87
10010Albert.B经济Charles.D线性代数65
10011Eric.F计算机Glen.H编译原理55
10011Eric.F计算机Glen.H计算机组成原理88
10011Eric.F计算机Glen.H计算机网络79
10012Isaac.J计算机Glen.H编译原理63
10012Isaac.J计算机Glen.H计算机组成原理59
10012Isaac.J计算机Glen.H计算机网络25

第一范式(1NF) 每一列都必须是不可分割的原子数据项

第二范式(2NF) 在1NF的基础上,非码属性必须完全依赖选码(在1NF的基础上消除非主属性对主码部分函数依赖)
函数依赖:通过A的属性能够确定唯一的B,则B依赖于A
完全函数依赖:如果A是一个属性组(多个属性),而B的值需要通过依赖属性组中所有的属性才能够确定
部分函数依赖:你懂的
传递函数依赖:通过A获得B,再通过B获得C
码:如果在一张表中,如果一个属性或者属性组被其他所有属性完全依赖,则称其为该表的码
主属性:码属性中的所有属性

根据2NF,拆分为:
主属性为学号

学号课程名称分数
10010高等数学95
10010大学英语87
10010线性代数65
10011编译原理55
10011计算机组成原理88
10011计算机网络79
10012编译原理63
10012计算机组成原理59
10012计算机网络25

主属性为学号

学号姓名系名系主任
10010Albert.B经济Charles.D
10011Eric.F计算机Glen.H
10012Isaac.J计算机Glen.H

第三范式(3NF) 在2NF的基础上,任何非主属性不依赖其他主属性(在2NF基础上消除传递依赖)
将上述表2再进行拆分,消除传递依赖:

学号姓名系名
10010Albert.B经济
10011Eric.F计算机
10012Isaac.J计算机
系名系主任
经济Charles.D
计算机Glen.H

备份:
mysqldump -u{user} -p{password} {database} > {path}
source {path}

多表查询
SELECT * FROM emp,dept
返回两表的笛卡尔积

内连接查询

--隐式
SELECT * FROM emp,dept WHERE emp.`dept_id` = dep.`id`;
--显式
SELECT * FROM emp JOIN dept ON emp.`dept_id` = dep.`id`;

也可以用多行书写:

SELECT
    t1.name,t1.gender,t2.name
FROM
    emp t1, dept t2
WHERE
    t1.`dept_id` = t2.`id`;

左外和右外

--查询的是左表所有的数据和右表交集
SELECT 字段 FROM 表1 LEFT JOIN 表2 ON 条件;

子查询

SELECT MAX(salary) FROM emp;
SELECT * FROM emp WHERE `salary` = 9000;
--合并两条
SELECT * FROM emp WHERE `salary` = (SELECT MAX(salary) FROM emp);
--上述子查询的结果是单行单列,可以直接作为条件使用
--单行多列时:
SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = 'A' OR NAME = 'B');
--多行多列时,可以将条件作为一张虚拟表:
SELECT * FROM dept t1, (SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2 WHERE t1.id = t2.dept_id;

事物
事物:如果一个包含多个步骤的业务操作,被事物管理,要么这些操作同时成功,要么同时失败
操作:开启START TRANSACTION-回滚ROLLBACK-提交COMMIT

SELECT @@AUTOCOMMIT;
--1 为自动提交  0为手动提交

事物四大特征:
1.原子性:不可分割,要么同时同时成功、要么同时失败
2.持久性:事物提交或者回滚之后,数据库会持久化的保存数据
3.隔离型:多个事物之间,相互独立
4.一致性:事物操作前后,数据总量不变
事物的隔离级别:
脏读:如果一个事物读到另一个事物没有提交的数据
不可重复读(虚读):在同一个事物中,两次读到的数据不一样
幻读:一个事物操作数据表中的所有记录,另一个事物添加了一条数据,则第一个事物查询不到自己的修改
隔离级别:

  1. READ-UNCOMMITTED 读未提交 //三种问题都有可能发生
  2. READ-COMMITTED 读已提交 //可以解决脏读
  3. REPEATABLE-READ 可重复度 //可以解决脏读、不可重复度 (默认)
  4. SERIALIZABLE 串行化 //可以解决所有的问题
SELECT @@TX_ISOLATION;  --查询隔离级别
SET GLOABL TRANSACTION ISOLATION LEVEL 级别字符串;  --设置隔离级别

DCL管理用户与授权

--查询
USE mysql;
SELECT * FROM USER;
--创建
CREATE USER '{user}'@'localhost' IDENTIFIED BY '{password}';
--删除
DROP USER '{user}'@'localhost';
--修改密码
UPDATE USER SET PASSWORD = PASSWORD('{new password}') WHERE USER = '{用户名}';
SET PASSWORD FOR '{user}'@'localhost' = PASSWORD('{new password}');
--无验证启动mysql
mysqld --skip-grant-tables
--查询权限
SHOW GRANTS FOR '{user}'@'localhost';
--授予权限
GRANT {permission} ON {database}.{table} TO '{user}'@'localhost';
--撤销权限
REVOKE UPDATE ON {database}.{table} FROM '{user}'@'localhost';

JDBC(Java DataBase Connectivity)

一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现该接口,提供数据库驱动jar包,真正执行的代码是驱动jar中的实现类。