目录
心情日记
又是新的一周,上周日考试分还是低,平常觉得自己写的代码还挺好,一到考试就不行,继续努力!!
重点归纳
1.JUnit单元测试
2.jar包、Test注解
3.集合的好多面试题
4.Stream编程(流式编程)
5.Stream具体能干什么
6.工具类:File----操作文件的类
(1)文件的路径
(2)File类的构造器
(3)文件的操作
知识点记录
JUnit单元测试
JUnit是一个Java语言单元测试框架
刚入职可能主要做的就是单元测试,很重要以前我们都用主方法测试代码,其实可以用JUnit,以后用JUnit代替主方法
JUnit单元测试的好处
1.可以书写一系列的测试方法,对项目所有的接口或者方法进行单元测试
2.启动后,自动化测试
3.只需要查看最后的结果
4.每个单元测试的用例相对独立,由JUnit启动
5.添加,删除,屏蔽测试方法
jar包
如果要引入第三方插件,其实引入的是xxx.jar文件
首先要把这个文件导入到我们的工程目录下
其次要添加到工程的依赖目录中Test注解是JUnit提供的一个单元测试注解
如果你的工程没有导入JUnit大jar包,Test注解是不认识的
建议用JUnit4jar包。
测试方法
1.不能有返回值
2.不能有参数列表
3.必须有Test注解
4.JUnit4中必须写public
JUnit5中可以不写,默认public
//JUnit单元测试
//Test注解
@Test
//测试方法
public void test01(){
System.out.println("hello junit01");
}
@Test
public void test02(){
System.out.println("hello junit02");
}
JUnit断言:assert
JUnit所有的断言都包含在一个类中---Assert类
这个类提供了很多有用的断言来编写测试用例
只有失败的断言才会被记录1.assertEquals():检查两个变量或等式是否向相等
2.assertTrue():检查条件是否为真
3.assertFalse():检查条件是否为假
4.assertNotNull():检查条件是否不是空
5.assertNull():检查条件是否为空断言不成功会抛异常,即使程序正常运行,但是结果不正确,也会以失败结束
@Test
public void test01(){
//类名.静态方法
Assert.assertTrue(false);
}
JUnit注解
1.Test
2.Before:在测试方法之前执行的方法
3.After:在测试方法之后执行的方法
命名规范
单元测试类的命名:被测试的类的类名 + Test
测试方法的命名:test + 被测试方法的方法名
@Test
public void test01(){
System.out.println("test01方法执行。。。");
}
@Test
public void test02(){
System.out.println("test02方法执行。。。");
}
@Before
public void testBefore(){
System.out.println("before方法执行。。。");
}
@After
public void testAfter(){
System.out.println("after方法执行。。。");
}
集合的好多面试题
1.Hashtable和ConcurrentHashMap(单线程)性能测试
ConcurrentHashMap(单线程):专门应付高并发的类2.ArrayList和LinkedList性能测试
数组查询快,插入慢;链表插入快,查询慢
1.尾插数组快,链表慢
2.遍历数组快
3.头插,链表快,数组慢
4.随机删除,如果要过滤(查多少个数大于多少)的话,建议用链表linkedlist开发中,还是arraylist为主
@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));
}
测试高并发
Hashtable和ConcurrentHashMap
我们测试开辟50个线程,每个线程相机和中put(添加) 100000个元素,
测试一下两个类所需时间
@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)); //慢
}
@Test
public void testConcurrentHashMap() throws InterruptedException {
final Map<Integer,Integer> map = new ConcurrentHashMap<>(500000);
// 计数器
// final CountDownLatch countDownLatch = new CountDownLatch(50);
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);
}
// 记录添加的数据次数
// countDownLatch.countDown();
}).start();
}
// countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("ConcurrentHashMap执行了:" + (end - start));//超快
}
JDK8新增法
Stream编程(流式编程)
容器对象功能的增强
我们可以先将流看成流水线,这个流水线是处理数据的流水线
当我们使用一个流的时候,通常有三个步骤:
1.获取一个数据源
2.执行操作获取想要的结果
3.每次操作,原有的流对象不改变,返回一个新的Stream对象
Stream有几个特性:
1.Stream不储存数据,一般会输出结果
2.Stream不会改变数据源,通常情况下会生成一个新的集合
3.Stream具有延迟执行的特性,只有调用终端操作时,中间操作才会执行可以用集合创建流,也可以用Stream.of、Stream.iterate静态方法创建流
@Test
public void test01() {
List<String> list = Arrays.asList("a","b","c");
// 创建一个顺序流
Stream<String> stream = list.stream();
// 创建一个并行流
Stream<String> parallelStream = list.parallelStream();
Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5, 6);
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
Stream具体能干什么
(建立一个Person类为例,在其基础上实验Stream的功能)
对集合的元素进行操作,可以获取指定规则的元素信息(例:判断有无大于35的数)
//创建一个复杂的集合
List<Person> personList = new ArrayList<>();
//创建一个简单的集合
List<Integer> simpleList = Arrays.asList(15,22,15,11,33,52,22,14,33,52);
@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,"女","南京"));
}
@Test
public void test01(){
// 打印集合元素
// 双冒号语法,方法引用
simpleList.stream().forEach(System.out::println);
// 其实还可以简化操作
simpleList.forEach(System.out::println);
}
@Test
public void test02() {
// 找到第一个元素
Optional<Integer> first = simpleList.stream().findFirst();
// 随便找一个
// 如果没有并行,any也是第一个
Optional<Integer> any = simpleList.stream().findAny();
System.out.println("第一个:" + first.get());
System.out.println("任意一个:" + any.get());
}
@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);
}
@Test
public void Ch07() {
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);
}
@Test
public void Ch08() {
// 统计
long count = new Random().ints().limit(50).count();
System.out.println(count);
OptionalDouble average = new Random().ints().limit(50).average();
average.ifPresent(System.out::println);
int sum = new Random().ints().limit(50).sum();
System.out.println(sum);
}
test9:
规约(reduce)缩减:把一个流缩减成一个值,可以实现求和、求乘积、求最值等
(规约是自己定义的)(了解)
@Test
public void test09(){
Integer result = simpleList.stream().reduce(1, (n1, n2) -> n1 - n2);
System.out.println(result);
}
test10:
Collector.joining("")将元素用”“里的字符分来
@Test
public void test10(){
List<String> list = Arrays.asList("A","B","C");
String string = list.stream().collect(Collectors.joining("-"));
System.out.println("拼接后的字符串:" + string);
}
test11:
分组将集合分为多个map,比如员工按性别分组,按薪水是否大于8000分组
(Boolean类型:true一组、false一组)
@Test
public void test11() {
// 根据工资分组
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);
}
test12:(重要)
过滤、筛选:filter
@Test
public void test12() {
simpleList.stream().filter(item -> item > 17).forEach(System.out::println);
// 筛选员工中工资大于8000的人,并形成新的集合
List<Person> collect = personList
.stream()
.filter(item -> item.getSalary() > 5000)
.collect(Collectors.toList());
System.out.println(collect);
}
test13:(重要)
映射:将一个流的元素,按照一定的映射规则映射到另一个流中
@Test
public void test13(){
// 将员工的工资全部增加1000
personList
.stream().map(item -> {
item.setSalary(item.getSalary() + 1000);
return item;
}).forEach(System.out::println);
List<StringBuilder> collect = simpleList.stream().map(item -> {
StringBuilder strb = new StringBuilder();
strb.append(item);
return strb;
}).collect(Collectors.toList());
System.out.println(collect);
}
test14:(重要)
排序:sorted,只要见到sorted就是排序的意思
有两种:自然排序(默认升序)、临时排序(传参)
@Test
public void test14() {
// 将员工按工资由低到高排序(自然排序--升序)
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);
}
test15:
peek操作:调试。
在Stream中调试,Stream不支持debug
@Test
public void test15(){
// 在stream中调试,stream不支持debug
List<Person> collect = personList.stream()
.filter(item -> item.getSalary() > 5000)
.peek(System.out::println)
.collect(Collectors.toList());
System.out.println(collect);
}
test16:
其他操作:合并、去重、限制、跳过。。。。。。
去重:distinct
跳过:skip,跳过几个数据
限制:限制使用几个数据
@Test
public void test16() {
simpleList
.stream()
.distinct()
.skip(2)
.limit(6)
.forEach(System.out::println);
}
Person类:
public class Person {
private String name;
private Integer salary;
private Integer age;
private String gender;
private String area;
public Person() {
}
public Person(String name, Integer salary, Integer age, String gender, String area) {
this.name = name;
this.salary = salary;
this.age = age;
this.gender = gender;
this.area = area;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSalary() {
return salary;
}
public void setSalary(Integer salary) {
this.salary = salary;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", salary=" + salary +
", age=" + age +
", gender='" + gender + '\'' +
", area='" + area + '\'' +
'}';
}
}
JDK8新增的函数式接口
1.Consumer<>消费者:void accept(T t)
2.Supplier<>供应商:给东西get()
3.Function:R apply(T t),将一个数据转化成另一个数据
4.Predicate断言:boolean test(T t),判断返回值是boolean
JDK8之后
Optional类:解决null问题
@Test
public void test01() {
String str = null;
// 返回一个对象值为空的Optional对象
Optional<String> empty = Optional.empty();
Optional<String> hello = Optional.of(str);
Optional<String> o = Optional.ofNullable(null);
System.out.println(o.get());
}
JDK8新增
1.函数是接口(必须会)
2.箭头函数(必须会)lambda表达式,不是Java特有的,Java里的只是阉割版
3.Optional类
4.断言
5.Stream编程IO流的前提知识:一些工具类
Java的IO流
IO:(Input、Output)
Input流:把数据从物理内存加载到 运行内存(读文件)
Output流:把数据从运行文件写到物理内存(写文件)用Java.IO包下的类实现输入输出
计算机的输入输出都是通过二进制完成
0/1
工具类:File----操作文件的类
1.文件的路径
路径分隔符:
正斜杠:左斜杠 /
反斜杠:右斜杠 \在Unix/Linux,路径的分隔采用正斜杠
在windows中,路径分隔采用反斜杠 \
在Java中正反斜杠都好使在Java中 \ 具有另一种意义:转义
所以如果想要写路径,要写两个 \\在File类中定义了路径分隔符常量,自动识别操作系统
File.separator = \
File.pathSeparator = ;
public static void main(String[] args) {
// System.out.println("\t");
// System.out.println("E:\\");
// System.out.println("E:/workspace");
System.out.println(File.separator);
System.out.println("e:" + File.separator + "workspace");
System.out.println(File.pathSeparator);
}
2.File类的构造器
文件的路径不要拼接,看实际场景选择构造器
public static void main(String[] args) {
// file就代表了当前的目录
File file1 = new File("E:\\workspace\\idea");
System.out.println("file1 = " + file1);
File file2 = new File("E:\\workspace\\idea","aaa");
System.out.println("file2 = " + file2);
File file3 = new File(file1,"aaa");
System.out.println("file3 = " + file3);
}
3.文件的操作
test01
创建文件时要抛异常(未找到目录异常)
createNewFile:创建新的文件,返回值boolean类型 */
@Test
public void test01() {
// 创建一个文件
File file1 = new File("e:\\aaa.txt");
try {
file1.createNewFile();
System.out.println("文件创建成功...");
} catch (IOException e) {
e.printStackTrace();
}
}
test02
delete 删除文件时File类的删除不走回收站,直接删除
@Test
public void test02(){
File file = new File("e:\\aaa.txt");
// 如果存在就删除,如果不存在就拉倒
// file类的删除是不走回收站
boolean delete = file.delete();
System.out.println(delete); }
test03
文件夹(目录) mkdir:创建新的文件夹。返回值boolean类型
mkdirs:创建多级文件夹。返回值boolean类型
mkdirs也可以创建一层,所以开发中一般用mkdirs
@Test
public void test03(){
File file = new File("e:/hello");
boolean mkdir = file.mkdir();
// file.delete();
// 删除文件夹
// delete:不走回收站
boolean b = file.mkdirs();
System.out.println(b);
try {
file.createNewFile();
System.out.println("创建成功...");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
test04
新建某一个路径下的某一个文件,且这个路径不存在,没有这个方法,需要我们封装工具类
思想1:
创建工具类里全是静态方法
思想2:
创建实体类
@Test
public void test04() throws IOException {
File file = new File("e:/hello/abc.txt");
// file.mkdirs();
// file.mkdir();
file.createNewFile(); }
封装类FileUtil:
import java.io.File;
import java.io.IOException;
public class FileUtil {
public static void createFile(File file){
if (file.exists()){
System.out.println("文件存在");
} else {
System.out.println("文件不存在,创建它");
if (!file.getParentFile().exists()){
file.getParentFile().mkdirs();
System.out.println("创建完成!");
}
try {
file.createNewFile();
}catch (IOException e){
e.printStackTrace();
}
}
}
// public void Creat(String pathname){
// createFile(new File(pathname));
// }
public static void main(String[] args) {
String pathName = "D:/hello/abc.txt";
createFile(new File(pathName));
}
}
test05
File类中判断方法:
1.exists:判断文件是否存在
2.isAbsolute:判断文件是不是绝对路径
绝对路径:以盘符开头的路径
相对路径:没有指定的盘符的路径。
创建时直接创建在当前工程目录下
3.isDirectory:判断是不是目录
4.isFile:是不是文件
5.isHidden:判断是不是隐藏文件
@Test
public void test05() throws IOException {
File file = new File("e:/aaa.txt");
File file2 = new File("E:\\idea");
System.out.println(file.isHidden());
System.out.println(file.isFile());
System.out.println(file2.isDirectory());
System.out.println(file.isAbsolute());
// 判断文件是否存在
System.out.println(file.exists());
// 新建文件是不会覆盖已有的文件
System.out.println(file.createNewFile());
System.out.println(file2.mkdirs());
}
test06
File类中的方法:
1.getAbsolutePath:
2.getAbsoluteFile:
3.getParent:
4.getParentFile:
5.getName
6.getPath
7.lastModified
8.length
@Test
public void test06() {
File file = new File("d:/123.txt");
File file1 = new File("bbb.txt");
System.out.println(file.getAbsolutePath());
System.out.println(file1.getAbsolutePath());
// 获取对应的相对路径的那个对象
File absoluteFile = file1.getAbsoluteFile();
// System.out.println(file.getParent());
File parentFile = file.getParentFile();
System.out.println(file.getName());
System.out.println(file1.getPath());
System.out.println(new Date(file.lastModified()));
System.out.println(file.length());
// 剪切粘贴 移动 file.renameTo(new File("d:\\aaa.txt"));
}
test07
文件夹列表的操作方法
1.list:获取当前文件夹下所有的文件夹的名,数组形式
2.listFiles:获取File形式,数组形式
@Test
public void test07() {
File file = new File("E:\\workspace");
String[] fileNames = file.list();
// System.out.println(Arrays.toString(fileNames));
File[] files = file.listFiles();
System.out.println(Arrays.toString(files));
}
@Test
public void test08() {
File file = new File("D:\\QQ");
File[] files = file.listFiles((f) -> {
if (f.isFile()) {
return true;
}
return false;
});
System.out.println(Arrays.toString(files));
String[] list = file.list((dir, name) -> {
if(dir.isDirectory()){
return true;
}
// if (name.endsWith("xml")) {
// return true;
// }
return false;
});
System.out.println(Arrays.toString(list));
}
练习
输入指定的磁盘名:直接进入到磁盘,
输入mkdir,创建目录
输入rd,删除文件
输入cnf:创建文件
输入dir:遍历当前目录的文件
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;
public class CMD {
//定义一个静态变量储存目录的路径
private static String M;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
main:
while (true) {
M = null;
System.out.println("请输入磁盘:");
String Pan = sc.next();
//以路径的方式存储盘
String Pan1 = Pan + ":\\";
File file = new File(Pan1);
if (file.exists()) {
System.out.println(file.getPath());
System.out.println("磁盘打开成功!");
}else {
System.out.println("没有此盘符重新输入:");
continue main;
}
CMD:while (true) {
System.out.println("请输入要进行的操作:1.mkdirs(创建目录)/t2.cnf(创建文件)/t3.rd(删除文件)/t4.dir(遍历当前目录的文件)/t5.cd(换磁盘)");
String flag = sc.next();
//重新打开磁盘时,清空目录路径,便于创建新的目录
switch (flag) {
case "mkdirs":
System.out.println("请输入目录名:");
//盘符加目录的路径
M = Pan1 + sc.next();
File file1 = new File(M);
//创建目录
if (!file1.exists()) {
file1.mkdirs();
} else {
System.out.println("当前目录已存在!");
}
continue CMD;
case "cnf":
System.out.println("请输入文件名:");
//目录加文件的路径
File file2 = new File(M + "\\" + sc.next());
//创建文件
try {
file2.createNewFile();
System.out.println("创建成功!");
} catch (IOException e) {
e.printStackTrace();
}
continue CMD;
case "rd":
System.out.println("请输入要删除文件名:");
//目录加文件的路径
File file3 = new File(M + "\\" + sc.next());
//删除文件
if (file3.exists()) {
file3.delete();
System.out.println("删除成功!");
} else {
System.out.println("没有找到文件!");
}
continue CMD;
case "dir":
//遍历目录所有文件
File file4 = new File(M);
String[] list = file4.list();
if (list.length != 0) {
System.out.println(Arrays.toString(list));
}else {
System.out.println("文件夹为空!");
}
continue CMD;
case "cd":
continue main;
default:
break;
}
}
}
}
}