2022-08-08 day25 第一小组 王鸣赫

Junit单元测试

什么是单元测试

针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。 程序单元是应用的最小可测试部件。简单来说,就是测试数据的稳定性是否达到程序的预期。

单元测试的重要性

有了测试的概念,这时候当我们做完项目的一个小模块,我们先去测试一下这个小模块是否正确或达到预期,如果错误或者没有达到预期就需要反复修改,直到正确或达到预期

Junit单元测试的好处:

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

@Test测试与Assert断言步骤

@Before和@After注解

有些应用场景,比如IO流的读写操作。如果我们要测试此代码,是需要一个关闭流的过程,通过我们关闭流使用finally块来保证最后流的关闭操作。这时,我们在Junit单元测试中,有一个@After注解,是用作资源的关闭。也就是说被@After注解修饰的方法会在测试方法之后自定执行。所以,我们在特定需要保证最后关闭、销毁资源的时候,可以去定义一个close方法,去关闭或销毁资源。这就是@After注解的作用!

注意: @Before和@After注解在程序报错的时候,仍然可以保证数据的初始化和关闭销毁,两个方法是依旧执行的。这里有点像我们tomact服务器的初始阶段和销毁阶段,它们的执行不受任何影响。

断言

1、assert condition;
这里condition是一个必须为真(true)的表达式。如果表达式的结果为true,那么断言为真,并且无任何行动。如果表达式为false,则断言失败,则会抛出一个AssertionError对象。这个AssertionError继承于Error对象,
而Error继承于Throwable,Error是和Exception并列的一个错误对象,通常用于表达系统级运行错误。
2、asser condition:expr;
这里condition是和上面一样的,这个冒号后跟的是一个表达式,通常用于断言失败后的提示信息,说白了,它是一个传到AssertionError构造函数的值,如果断言失败,该值被转化为它对应的字符串,并显示出来。

Stream流

什么是流

Stream不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的Iterator。原始版本的Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的Stream,用户只要给出需要对其包含的元素执行什么操作,比如,“过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream会隐式地在内部进行遍历,做出相应的数据转换。Stream就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。

  而和迭代器又不同的是,Stream可以并行化操作,迭代器只能命令式地、串行化操作。顾名思义,当使用串行方式去遍历时,每个item读完后再读下一个item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。Stream的并行操作依赖于Java7中引入的Fork/Join框架(JSR166y)来拆分任务和加速处理过程。

  Stream 的另外一大特点是,数据源本身可以是无限的。

流的操作类型

流的操作类型分为两种:

Intermediate:一个流可以后面跟随零个或多个intermediate操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。

Terminal:一个流只能有一个terminal操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以,这必定是流的最后一个操作。Terminal操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个side effect。

点击查看代码
// 1. Individual values
Stream stream = Stream.of("a", "b", "c");

// 2. Arrays
String [] strArray = new String[] {"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);

// 3. Collections
List<String> list = Arrays.asList(strArray);
stream = list.stream();

流的操作

  接下来,当把一个数据结构包装成Stream后,就要开始对里面的元素进行各类操作了。常见的操作可以归类如下:

Intermediate 操作

 map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

Terminal 操作

 forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

Short-circuiting 操作

 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

map/flatMap

它的作用就是把inputStream的每个元素映射成outputStream的另外一个元素

Stream<List<Integer>> inputStream = Stream.of( Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6) ); Stream<Integer> outputStream = inputStream. flatMap((childList) -> childList.stream());

filter

 filter对原始Stream进行某项测试,通过测试的元素被留下来生成一个新Stream。
// 留下偶数 Integer[] sixNums = {1, 2, 3, 4, 5, 6}; Integer[] evens = Stream.of(sixNums).filter(n -> n%2 == 0).toArray(Integer[]::new);

forEach

 forEach方法接收一个Lambda表达式,然后在Stream的每一个元素上执行该表达式。
// 对一个人员集合遍历,找出男性并打印姓名。 roster.stream().filter(p -> p.getGender() == Person.Sex.MALE) .forEach(p -> System.out.println(p.getName()));

findFirst

 这是一个termimal兼short-circuiting操作,它总是返回Stream的第一个元素或者空。
`// Optional 的两个用例:以下两组示例是等价的

// Java 8
Optional.ofNullable(text).ifPresent(System.out::println);

// Pre-Java 8
if (text != null) {
System.out.println(text);
}

//----------

// Java 8
return Optional.ofNullable(text).map(String::length).orElse(-1);

// Pre-Java 8
return if (text != null) ? text.length() : -1;
};`

Stream 的特性可以归纳为:

不是数据结构;

它没有内部存储,它只是用操作管道从source(数据结构、数组、generator function、IO channel)抓取数据;

它也绝不修改自己所封装的底层数据结构的数据。例如Stream的filter操作会产生一个不包含被过滤元素的新Stream,而不是从source删除那些元素;

所有Stream的操作必须以lambda表达式为参数;

不支持索引访问;

你可以请求第一个元素,但无法请求第二个,第三个,或最后一个;

很容易生成数组或者List;

惰性化;

很多Stream操作是向后延迟的,一直到它弄清楚了最后需要多少数据才会开始;

Intermediate操作永远是惰性化的;

并行能力;

当一个 Stream 是并行化的,就不需要再写多线程代码,所有对它的操作会自动并行进行的;

可以是无限的。集合有固定大小,Stream 则不必。limit(n)和findFirst()这类的short-circuiting操作可以对无限的Stream进行运算并很快完成。

集合的面试题

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
    }

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));
    }

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

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

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");

文件的操作
绝对路径和相对路径

绝对路径:以盘符开头
相对路径:没有指定的盘符开头. 使用相对路径创建文件会创建到相对工程的路径下

点击查看代码
//创建一个文件,不会覆盖已有的同名文件
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数组

posted @ 2022-08-08 22:12  404notfond  阅读(10)  评论(0)    收藏  举报