Junit单元测试

JUnit是一个Java语言单元测试框架

Junit单元测试的好处:

  1. 可以书写一些列的测试方法,对项目的所有的接口或者方法进行单元测试
  2. 启动后,自动化的测试
  3. 只需要查看最后的结果
  4. 每个单元测试的用例是相对独立
  5. 添加、删除、屏蔽测试方法

jar包
如果要引入第三方的插件,xxx.jar的文件
首先要把这个文件导入到工程目录下
其次,要添加到工程的依赖目录中

测试方法:

    • 不能有返回值
    • 不能有参数列表
      • 必须有Test注解
import org.junit.Test;
public class Ch01 {

//Test注解是Junit提供的一个单元测试注解
//如果你的工程没有导入Junit的jar包,Test注释是不认识的
    @Test
    public void MyTest01(){
        System.out.println(111);
    }
}

Junit的断言

Junit的所有的断言都包含在Assert类中,这个类提供了很多有用的断言赖编写测试用例,只有失败的断言才会被记录
断言不成功会抛异常,即使程序正常运行但是结果不正确,也会以失败结束

Junit的一些常用方法

  1. assertEquals:检查两个变量或等式是否平衡
  2. assertTrue:检查条件是否为真
  3. assertFalse:检查条件是否为假
  4. assertNotNull:检查对象是否不为空
  5. assertNull:检查对象是否为空

Junit的注释

  1. Test
  2. Before:在测试方法执行之前执行的方法
  3. After:在测试方法执行之后执行的方法

命名规范

  • 单元测试类的命名:被测试类的类名+Test
  • 测试方法的命名:test + 被测试方法的方法名
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class Ch03Test {

    @Test
    public void testMyTest01(){
        System.out.println(1);
    }

    @Before
    public void testMyTest02(){
        System.out.println(2);
    }

    @After
    public void testMyTest03(){
        System.out.println(3);
    }
    
    //输出2 1 3
}

Stream编程

容器对象功能的增强,可将流看做流水线,这个流水线是处理数据的流水线

当使用一个流的时候,通常包括3个步骤:

  1. 获取一个数据源
  2. 执行操作获取想要的结果
  3. 每次操作,原有的流对象不改变,返回一个新的Stream对象
@Test
    public void test01(){
        List<String> list = Arrays.asList("a","b","c");
        //创建一个顺序流
        Stream<String> stream = list.stream(); // a b c
        Stream<Integer> stream1 = Stream.of(1,2,3,4,5,6);  // 1,2,3,4,5,6
        //创建一个并行流
        Stream<String> parallelStream = list.parallelStream();
        //从零开始每次递增3   限制长度为4
        Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);//0 3 6 9
    
        stream.forEach(System.out::println);//输出语句
    }

Stream有几个特性

  1. Stream不存储数据,一般会输出结果
  2. Stream不会改变数据源,通常情况下会生成一个新的集合
  3. Stream具有延迟执行的特性,只用调用终端操作时,中间操作才会执行

Stream的常用方法

@Before:在测试方法之前执行
@Test:测试方法
@After:在测试方法之后执行

    @Test
    public void test01() {
        System.out.println(0);
    }
    @Before
    public void test02(){
        System.out.println(1);
    }
    @After
     public void test03(){
        System.out.println(2);
    }
    //输出 1 0 2

总结:

  1. 该方法是将数组转化成List集合的方法,用此方法得到的List的长度是不可改变的
  2. 如果你的List只是用来遍历,就用Arrays.asList()。
  3. 如果你的List还要添加或删除元素,还是乖乖地new一个java.util.ArrayList,然后一个一个的添加元素。
    //创建一个复杂的集合
    List<Person> personList = new ArrayList<>();
    //创建一个简单的集合
    List<Integer> simpleList = Arrays.asList(15, 22, 9, 11, 33, 52, 14);
    @Before
    public void before() {
        personList.add(new Person("张三", 3000, 23, "男", "长春"));
        personList.add(new Person("李四", 7000, 34, "男", "西安"));
        personList.add(new Person("王五", 5000, 22, "女", "长春"));
        personList.add(new Person("小明", 1000, 33, "女", "上海"));
        personList.add(new Person("小红", 8000, 44, "女", "北京"));
        personList.add(new Person("小黑", 6000, 36, "女", "南京"));
    }

forEach()方法:增加for循环,只能用于遍历

    @Test
    public void test01() {
        //打印集合元素
        //双冒号语法,方法引用
        simpleList.stream().forEach(System.out::println);
        //简化操作
        simpleList.forEach(System.out::println);
    }

findFirst():找第一个元素
findAny():找任意一个元素,如果没有并行,any也会找第一个元素

    @Test
    public void test02() {
      
        Optional<Integer> first = simpleList.stream().findFirst();

        Optional<Integer> any = simpleList.stream().findAny();

        System.out.println("第一个:" + first.get());
        System.out.println("任意一个:" + any.get());
    }

anyMatch:任意匹配,只要一个匹配成功就为true
allMatch:全部匹配,全部匹配成功就为true

    @Test
    public void test03(){
        //判断有没有任意一个人年龄大于35
        boolean b = personList.stream().anyMatch(item -> item.getAge() > 35);
        System.out.println(b);

        // 判断是不是所有人年龄都大于35岁
        b = personList.stream().allMatch(item -> item.getAge() > 35);
        System.out.println(b);
    }

Collectors.toList():转为List集合返回
Collectors.toSet():转为Set集合返回
Collectors.toMap():转为Map集合返回

    @Test
    public void test04() {
        List<Integer> collect = simpleList.stream().collect(Collectors.toList());
        System.out.println(collect);
        Set<Integer> collect1 = simpleList.stream().collect(Collectors.toSet());
        System.out.println(collect1);
        Map<Integer, Integer> map = simpleList.stream().collect(Collectors.toMap(item -> item, item -> item + 1));
        System.out.println(map);
    }

利用stream流快速生成不重复数字集合

  • 示例:随机生成0~300范围内 50个不重复的数字
    @Test
    public void test05() {
        long count = new Random().ints(生成数字最小值, 生成数字最大值).limit(取多少个数字).count();
    }
    list = new Random().ints(0 300)
                .distinct().limit(50).boxed().collect(Collectors.toList());

归约(reduce)缩减,把一个流缩减成一个值,
可以实现对集合的求和,求乘积,求最值

    @Test
    public void test06(){
        Integer result = simpleList.stream().reduce(1, (n1, n2) -> n1 - n2);
        System.out.println(result);
    }

    @Test
    public void test07(){
        List<String> list = Arrays.asList("A","B","C");
        String string = list.stream().collect(Collectors.joining("-"));
        System.out.println("拼接后的字符串:" + string);
    }

分组将集合分为多个map,groupingBy()方法

    @Test
    public void test08() {
        // 根据工资分组
        Map<Boolean, List<Person>> collect = personList.stream().collect(Collectors.groupingBy(x -> x.getSalary() > 5000));
        System.out.println(collect);
        // 根据性别分组
        Map<String, List<Person>> collect1 = personList.stream().collect(Collectors.groupingBy(Person::getGender));
        System.out.println(collect1);

        // 将员工根据性别分组,再按地区分组
        Map<String, Map<String, List<Person>>> collect2 = personList.stream()
                .collect(Collectors.groupingBy(Person::getGender, Collectors.groupingBy(Person::getArea)));
        System.out.println(collect2);
    }

筛选:filter()方法

    @Test
    public void test09() {
        // 筛选员工中工资大于8000的人,并形成新的集合
        List<Person> collect = personList
                .stream()
                .filter(item -> item.getSalary() > 5000)
                .collect(Collectors.toList());
        System.out.println(collect);
    }

映射

  • 将一个流的元素按照一定的映射规则映射到另一个流中。
    @Test
    public void test10(){
        List<StringBuilder> collect = simpleList.stream().map(item -> {
            StringBuilder strb = new StringBuilder();
            strb.append(item);
            return strb;
        }).collect(Collectors.toList());
        System.out.println(collect);
    }

排序:sorted

    @Test
    public void test11() {
        // 将员工按工资由低到高排序(自然排序--升序)
        List<String> collect = personList.stream()
                .sorted(Comparator.comparing(Person::getSalary))
                .map(Person::getName)
                .collect(Collectors.toList());
        System.out.println(collect);
        // 按照员工工资的降序
        List<String> collect1 = personList
                .stream()
                .sorted(Comparator.comparing(Person::getSalary).reversed())
                .map(Person::getName)
                .collect(Collectors.toList());
        System.out.println(collect1);
    }

其他操作:合并、去重、限制、跳过.....

    @Test
    public void test13() {
        /*
            distinct:去重
            skip:跳过几个数据
            limit:限制使用几个数据
         */
        simpleList
                .stream()
                .distinct()
                .skip(2)
                .limit(6)
                .forEach(System.out::println);
    }

集合的面试题

  1. Hashtable和ConcurrentHashMap性能测试
    @Test
    public void hashtableTest() throws InterruptedException {
        final Map<Integer,Integer> map = new Hashtable<>(500000);
        System.out.println("开始测试hashtable-----------------------");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 50; i++) {
            final int j = i;
            new Thread(()->{
                for (int k = 0;k < 100000;k++){
                    map.put(j*k,1);
                }
            }).start();
        }
        long end = System.currentTimeMillis();
        System.out.println("hashtable执行了:" + (end - start)); // 1043ms
    }
    @Test
    public void testConcurrentHashMap() throws InterruptedException {
        final Map<Integer,Integer> map = new ConcurrentHashMap<>(500000);
        System.out.println("开始测试ConcurrentHashMap-----------------------");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 50; i++) {
            final int j = i;
            new Thread(()->{
                for (int k = 0;k < 100000;k++){
                    map.put(j*k,1);
                }
            }).start();
        }
        long end = System.currentTimeMillis();
        System.out.println("ConcurrentHashMap执行了:" + (end - start)); // 71ms
    }
  1. ArrayList和LinkedList性能测试
    @Test
    public void testArrayList() {
        List<Integer> list = new ArrayList<>();

        for (int i = 0; i < 10000000; i++) {
         list.add((int)(Math.random()*100));
        }
        long start = System.currentTimeMillis();

        Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()) {
            // 随机删除
            if(iterator.next() > 500){
                iterator.remove();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("arraylist用时:" + (end - start));
    }
    @Test
    public void testLinkedList() {
        List<Integer> list = new LinkedList<>();

        for (int i = 0; i < 10000000; i++) {
            list.add((int)Math.random()*100);
        }
        long start = System.currentTimeMillis();
        
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            if(iterator.next() > 500){
                iterator.remove();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("linkedlist用时:" + (end - start));
    }

数据查询快,插入慢
链表插入快,查询慢

  1. 尾插数组快,链表慢
  2. 遍历,数组快
  3. 头插,链表快,数组慢
  4. 随机删除,如果要过滤,建议用LinkedList

开发中,还是以arrayList为主

JDK8函数式接口

  1. Consumer:消费者 void accept(T t)
  2. Supplier:供应商 T get()
  3. Function:R apply(T t),将一个数据转化成另一个数据
  4. Predicate:断言,boolean test(T t),判断返回值是Boolean

JDK8新增:
1、函数式接口
2、箭头函数(Lambda表达式)
3、Optional类
4、断言
5、Stream编程

Optional类

Optional类是java8为了解决null问题,可以避免空指针异常

     @Test
    public void test01(){
        //返回一个对象值为空的Optional对象
        Optional<String> empty = Optional.empty();
        Optional<String> hello = Optional.of("hello");
        System.out.println(empty.get());
        Optional<String> o = Optional.ofNullable(null);
        System.out.println(o.get());
    }

IO流

Input:把数据从物理内存加载到运行内存(读文件)
Output:把数据从运行内存写到物理内存(写文件)

工具类:File操作文件的类
在File类中,定义了路径分隔符的常量,自动识别操作系统
1、文件的;路径
正斜杠(左斜杠、撇)/
反斜杠(右斜杠、捺)
在Unix/Linux,路径的分隔采用正斜杠
在Windows中,路径的分隔采用反斜杠

在java中,\代表转义

File类的构造器

1.File file1 = new File("E:\\code\\视频");
2.File file2 = new File("E:\\code\\视频","a");
File file3 = new File(file1,"aaa");

文件的操作

绝对路径和相对路径

  1. 绝对路径:以盘符开头
  2. 相对路径:没有指定的盘符开头. 使用相对路径创建文件会创建到相对工程的路径下
//创建一个文件,不会覆盖已有的同名文件
File file = new File("E:\\aaa.txt");

//判断文件是否存在
System.out.println(file.exists());

//判断文件路径是否为绝对路径
System.out.println(file.isAbsolute());

file.delete()//存在就删除,不存在就拉倒。file类中删除不走回收站

file.mkdir()//创建一级文件夹
file.mkdirs()//创建多级文件夹

file.list()//返回某个目录下的所有文件和目录的文件名,返回的是String数组
file.listFiles()//返回某个目录下所有文件和目录的绝对路径,返回的是File数组