今日重点:
目录
1、Hashtable和ConcurrentHashMap性能测试
1.函数式接口 2.箭头函数(lambda表达式),不是java特有的。 3.Optional类 4.断言 5.Stream编程
一、JUnit单元测试
1、概念
JUnit是一个Java语言单元测试框架。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。
2、JUnit单元测试的好处
(1)可以书写一些列的测试方法,对项目的所有的(数据)接口或者方法进行单元测试。
(2)启动后,自动化的测试,并且判断执行结果,不需要人为的干预。
(3)只需要查看最后的结果,就可以知道整个项目的方法接口是否通畅。
(4)每个单元测试用例相对独立,由JUnit启动,自动调用,不需要添加额外的调用语句。
(5)添加,删除,屏蔽测试方法,不影响其他的测试方法,开源框架都对JUnit有相应的支持。3、jar包
如果要引入第三方的插件,其实引入的都是xxx.jar的文件。首先要把这个文件导入到我们的工程目录下,其次要添加到工程的依赖目录中。
比如要使用@Test注解
如果工程中没有导入jar包,程序是不认识@Test注解的。
4、JUnit单元测试的使用(测试)方法
要求:
(1)不能有返回值
(2)不能有参数列表
(3)必须有Test注解
package com.jsoft.morning; import org.junit.Test; public class Ch01 { @Test public void test01(){ System.out.println("hello junit01"); } @Test public void test02() { System.out.println("hello junit02"); } }
以前一个类中我们只有一个主方法可以运行,现在通过JUnit测试方法,两个方法都可以运行了,再写多个方法也是可以的 。
5、JUnit断言
断言不成功会抛异常(会报错),即使程序正常运行但是结果不正确,也会以失败结束。
JDK1.8新出的功能,用来测试程序功能好不好使的的功能, JUnit断言提供了一些辅助函数,用于帮助开发人员确定某些被测试函数是否工作正常,断言是单元测试最基本的组成部分。JUnit的所有断言都包含在Assert类中,这个类提供了很多有用的断言来编写测试用例,只有失败的断言才会被记录。Assert 类中的一些有用的方法列式如下:
常用方法
① assertEquals:
检查两个变量或等式是否平衡
② assertTrue:检查条件是否为真
③ assertFalse:检查条件是否为假
④ assertNotNull:检查对象是否不为空
⑤ assertNull:检查对象是否为空
6、JUnit注解
(1) Test注解
这个注释说明依附在 JUnit 的 public void 方法可以作为一个测试案例。
(2) Before
有些测试在运行前需要创造几个相似的对象。在 public void 方法加该注释是因为该方法需要在 test 方法前运行。
(3)After
如果你将外部资源在 Before 方法中分配,那么你需要在测试运行后释放他们。在 public void 方法加该注释是因为该方法需要在 test 方法后运行。
package com.jr.morning; import org.junit.After; import org.junit.Before; import org.junit.Test; /* JUnit注解 1.Test 2.Before 3.After */ public class Ch03 { @Test public void test01(){ System.out.println("test01方法执行。。。"); } @Test public void test02(){ System.out.println("test02方法执行。。。"); } @Before public void testBefore(){ System.out.println("testBefore方法执行。。。"); } @After public void testAfter(){ System.out.println("testBefore方法执行。。。"); } }
7、JUnit命名规范
(1)单元测试类的命名
被测试类的类名 + Test
(2)测试方法的命名
test + 被测试方法的方法名
JUnit测试方法参考文章:https://www.jianshu.com/p/a3fa5d208c93
二、集合的面试题
我们尝试开辟50个线程,每个线程向集合中put 100000个元素,测试两个类所需的时间
1、Hashtable和ConcurrentHashMap性能测试
package com.jr.morning; import org.junit.Test; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; /* 集合的好多面试 1. Hashtable和ConcurrentHashMap性能测试 */ public class Ch04 { /* 我们尝试开辟50个线程,每个线程向集合中put100000个元素, 测试两个类所需的时间 */ @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); 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 } }
2、ArrayList和LinkedList性能测试
(1)按顺序添加元素效率
package com.jr.morning; import org.junit.Test; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; /* 集合的好多面试 1. Hashtable和ConcurrentHashMap性能测试 */ public class Ch04 { @Test public void testArrayList() { List<Integer> list = new ArrayList<>(); long start = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { list.add((int)Math.random()*100); } long end = System.currentTimeMillis(); System.out.println("arraylist用时:" + (end - start)); } @Test public void testLinkedList() { List<Integer> list = new LinkedList<>(); long start = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { list.add((int)Math.random()*100); } long end = System.currentTimeMillis(); System.out.println("linkedlist用时:" + (end - start)); } }
(2)查询效率
①for循环实现查询
package com.jr.morning; import org.junit.Test; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; /* 集合的好多面试 1. Hashtable和ConcurrentHashMap性能测试 */ public class Ch04 { @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(); for (int i = 0; i < list.size(); i++) { list.get(i);//千万别打印,电脑可能会崩 } 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(); for (int i = 0; i < list.size(); i++) { list.get(i);//千万别打印,电脑可能会崩 } long end = System.currentTimeMillis(); System.out.println("linkedlist用时:" + (end - start)); } }
②用迭代器实现查询
package com.jr.morning; import org.junit.Test; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; /* 集合的好多面试 1. Hashtable和ConcurrentHashMap性能测试 */ public class Ch04 { @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()){ iterator.next(); } 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()){ iterator.next(); } long end = System.currentTimeMillis(); System.out.println("linkedlist用时:" + (end - start)); } }
根据上面的结果, 说明数组非常适合进行元素的查询,但是链表就不适合,因为它会从头一个个看,看10000000次,时间就会非常久。
(3)删除效率
package com.jr.morning; import org.junit.Test; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; /* 集合的好多面试 1. Hashtable和ConcurrentHashMap性能测试 */ public class Ch04 { @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)); } }
3、测试结果总结
总结数组查询快,插入慢,链表插入快,查询慢
①尾插数组快,链表慢
②遍历,数据快
③头插,链表快,数组慢
④随机删除,如果要过滤,建议用inkedlist
开发中,还是以ArrayList为主,在开发的场景中用得最多
三、Stream流式编程
1、概念
JDK8新增的功能---Stream编程,是容器对象功能的增强
Stream 中文称为 “流”,通过将集合转换为这么一种叫做 “流” 的元素序列,通过声明性方式,能够对集合中的每个元素进行一系列并行或串行的流水线操作。
换句话说,你只需要告诉流你的要求,流便会在背后自行根据要求对元素进行处理,而你只需要 “坐享其成”。
2、使用流的三个步骤
1.获取一个数据源
2.执行操作获取想要的结果
3.每次操作,原有的流对象不改变,返回一个新的Stream对象
3、Stream的特性
(1)stream不存储数据,一般会输出结果
(2)stream不会改变数据源,通常情况下会生成一个新的集 合
(3)Stream具有延迟执行的特性,只有调用终端操作时,中间操作才 会执行。
四、Stream流式编程使用示例
1、创建流的几种常见方式
(1)用集合方式创建流
package com.jr.morning; import org.junit.Test; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Ch05 { @Test public void test01() { List<String> list = Arrays.asList("a","b","c"); // 创建一个顺序流 Stream<String> stream = list.stream(); // 创建一个并行流 Stream<String> parallelStream = list.parallelStream(); } }
(2)用到静态方法创建流(做个了解即可)
package com.jr.morning; import org.junit.Test; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Ch05 { @Test public void test01() { Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5, 6); Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4); } }
2、具体案例(具体能干什么)
(1)创建一个person类
对person类中的属性进行生成构造方法,生成set、get方法,生成toString
package com.jr.morning; 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 + '\'' + '}'; } }
(2)测试类Ch06
package com.jsoft.morning; import org.junit.Before; import org.junit.Test; import java.lang.invoke.VarHandle; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; public class Ch06 { // 创建一个复杂的集合 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); } /* 归约(reduce)缩减,把一个流缩减成一个值, 可以实现对集合的求和,求乘积,求最值 */ @Test public void test09(){ Integer result = simpleList.stream().reduce(1, (n1, n2) -> n1 - n2); System.out.println(result); } @Test public void test10(){ List<String> list = Arrays.asList("A","B","C"); String string = list.stream().collect(Collectors.joining("-")); System.out.println("拼接后的字符串:" + string); } /* 分组将集合分为多个map, 比如员工按性别分组 员工按薪资是否高于8000分组 */ @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); } /** * 筛选 */ @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); } /** * 映射 * 将一个流的元素按照一定的映射规则映射到另一个流中。 */ @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); } /** * 排序: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); } /** * peek操作,调试 */ @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); } /** * 其他操作:合并、去重、限制、跳过。。。。 */ @Test public void test16() { /* distinct:去重 skip:跳过几个数据 limit:限制使用几个数据 */ simpleList .stream() .distinct() .skip(2) .limit(6) .forEach(System.out::println); } }
3、具体案例分段解析其使用方法
(1)打印集合元素
其中用到forEach();方法,括号里写的就是我们想要实现的功能,括号里out后面不能用 . 得用双冒号::语法,进行方法引用。
simpleList.stream().forEach(System.out::println);
其实还可以简化操作:
simpleList.forEach(System.out::println);
(2)查找元素
①找到第一个元素
Optional<Integer> first = simpleList.stream().findFirst(); System.out.println("第一个:" + first.get());
②随便找一个元素
运行结果显示的也是第一个元素15,因为单线程没有并行,any找到的元素也是第一个元素。Optional<Integer> any = simpleList.stream().findAny(); System.out.println("任意一个:" + any.get());
(3)判断元素
①anyMatch();方法---任意匹配。
括号中应该写什么?函数式接口,传入一个参数,传入的参数代表的就是要判断的类的对象,返回值是Boolean类型。(allMatch();方法也是如此)
比如这里item代表的就是Person类,item.getAge()就是表示调用Person类的年龄属性// 判断有没有任意一个人年龄大于35岁,以前的做法是遍历集合然后进行判断 // anyMatch();方法---任意匹配。 boolean b = personList.stream().anyMatch(item -> item.getAge() > 35); System.out.println("有没有任意一个人年龄大于35岁"+b);
② allMatch();方法---全部匹配。
// 判断是不是所有人年龄都大于35岁 //allMatch();方法---全部匹配。 b = personList.stream().allMatch(item -> item.getAge() > 35); System.out.println("是不是所有人年龄都大于35岁"+b);
(4)收集元素
① 判断有没有任意一个人年龄大于35岁,收集起来
collect();方法---收集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);
②collect();方法收集集合中的元素,想要输出可以用joining(""));分隔元素
List<String> list = Arrays.asList("A","B","C"); String string = list.stream().collect(Collectors.joining("-")); System.out.println("拼接后的字符串:" + string);
(5)统计
①输出50,表示50这有个随机数
long count = new Random().ints().limit(50).count(); System.out.println(count);
②输出50个随机数的平均数
OptionalDouble average = new Random().ints().limit(50).average(); average.ifPresent(System.out::println);
③输出50个随机数的总和
int sum = new Random().ints().limit(50).sum(); System.out.println(sum);
(6)归约(reduce)缩减
归约(reduce)缩减,把一个流缩减成一个值,可以实现对集合的求和,求乘积,求最值,求减...
// 求减 Integer result1 = simpleList.stream().reduce(1, (n1, n2) -> n1 - n2); System.out.println(result1); // 求乘积 Integer result2 = simpleList.stream().reduce(1, (n1, n2) -> n1 *n2); System.out.println(result2); // 求和 Integer result3 = simpleList.stream().reduce(1, (n1, n2) -> n1 + n2); System.out.println(result3);
(7)分组
分组将集合分成多个map, 用到 collect();方法---收集
// 根据工资分组 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);
(8)筛选
①筛选集合中数大于17的数字,并形成新的集合
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);
(9)映射
将一个流的元素按照一定的映射规则映射到另一 个流中。
将员工的工资全部增加1000personList .stream().map(item -> { item.setSalary(item.getSalary() + 1000); return item; }).forEach(System.out::println);
(10)排序---sorted
①自然排序,默认就是升序
将员工按工资由低到高排序
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);
知识点补充请参考文章:https://blog.csdn.net/qq_21918021/article/details/88824335
五、JDK8函数式接口
1、Consumer<T>
消费者 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表达式),不是java特有的。
3.Optional类
4.断言
5.Stream编程
七、Java---IO 流
1、概念
IO是Input、Output两个首单词的缩写,输入输出流,是对于文件的操作
2、Input、Output
java.io包下的类是对input输入、output输出的支持。计算机的输入输出都是通过二进制完成,0和1。
input输入:把数据从物理内存加载到运行内存(读文件)
output输出:把数据从运行内存写到物理内存(写文件)
(1)本地传输:
把C盘的文件读出来,读到内存当中。把内存中数据保存到D盘,写到D盘。
(2)网络传输:
从我的电脑传输文件到你的电脑,从我的C盘中读取数据,先加载到我的内存中,然后通过网络传输(网络IO)传到你的内存里,再从你的内存中通过输出传到你的C盘。
(3) 对象传输:
在我的内存中,有个方法区,方法区里有个张三常量。栈有个对象User。有个推内存,里面有个name属性。name属性会指向方法区的张三常量,推内存的地址会指向User对象。最终传输的过程,会先加载成二进制,然后有两种方式,一种是写进我的C盘,或者通过网络传输传到其他电脑。
3、工具类:File操作文件的类
在真正学IO流之前,先学一个工具类File--操作文件的类。
(1)文件的路径
①文件路径的分隔符:
正斜杠:左斜杠,撇,/
反斜杠:右斜杠,捺,\在Unix或者Linux中,路径的分隔采用正斜杠 /。
在windows中,路径分隔采用反斜杠\,其实用正斜杠/也是好使的。
在Java中,反斜杠\ 代表转义,如果要打印输出文件地址,用正斜杠/或者得用两个反斜杠\\。
②在java中除了用斜杠输出打印文件地址,File类中还定义了路径分隔符的常量File.separator和File.pathSeparator,它们分别对象代表的是\和;
这两个常量会自动识别操作系统,如果是在window系统下生成的就是反斜杠\,如果是Linux系统下生成的就是正斜杠/。
(2)File类的构造器
有四种构造方式,常用的是前三种。为什么要整出三个构造器?为的就是尽量不要出现拼接字符串
package com.jr.afternoon; import java.io.File; /* file类的构造器 */ public class Ch02 { public static void main(String[] args) { //第一种 是最简单的一种构造器。File就代表了当前的目录 File file1 = new File("E:\\jiruan\\workplace"); System.out.println("file1="+file1); // 第二种 可以传两个,前面是父级目录,后面是子级目录 File file2 = new File("E:\\jiruan\\workplace","java"); System.out.println("file2="+file2); //第三种 file1是父级目录 File file3 = new File(file1,"Java"); System.out.println("file3="+file3); } }
八、文件的操作
1、创建文件
创建文件命令----file.createNewFile();
createNewFile--新建文件是不会覆盖已有的文件
使用这个命令的时候会抛出异常,因为程序怕系统没有父级菜单,无法创建后续文件。
package com.jr.afternoon; import java.io.File; import java.io.IOException; /* 文件的操作 createNewFile--新建文件是不会覆盖已有的文件 绝对路径:以盘符开头 相对路径:没有指定的盘符开头 */ public class Ch03 { public static void main(String[] args) { File file = new File("e:\\java.txt"); try { file.createNewFile(); System.out.println("创建文件成功"); } catch (IOException e) { e.printStackTrace(); } } }
2、删除文件
删除文件命令--- boolean delete = file.delete();
使用这个命令的时候不会抛出异常,因为如果存在就删除,如果不存在就拉倒。File类的删除是不走回收站。
import java.io.File; public class Ch03 { public static void main(String[] args) { //删除文件 File file = new File("e:\\java.txt"); boolean delete = file.delete(); System.out.println(delete); } }
3、创建和删除文件夹
创建文件夹的命令
boolean mkdir = file.mkdir();---创建一级文件夹
boolean mkdir = file.mkdirs();---创建多级文件夹(多级的也可以只创建一级)
删除文件夹的命令
file.delete();
package com.jr.afternoon; import java.io.File; public class Ch03 { public static void main(String[] args) { //创建文件夹 File file = new File("e:/a"); boolean mkdir = file.mkdir(); System.out.println(mkdir); } }
4、创建文件夹以及此文件夹下的文件
没有直接的命令,需要封装工具类。
package com.jr.afternoon; import java.io.File; import java.io.IOException; /* 创建文件夹以及此文件夹下的文件,需要封装工具类 分析: 传入可能有三种方式: 1.传入的路径是一个e:/a/b/c/bbb. txt 2.传入的路径是一个e:\\a\\bc\\aaa. txt 3.传入的路径是一个e:\a\b\c\aaa. txt */ public class FileUtil { public static boolean createDirAndFile(String filepath) throws IOException { File file = null; if(filepath.contains("/")){ if(filepath.contains("\\")){ throw new RuntimeException("路径不合法"); }else { // e:\\a\\b\\c\\a.txt int index = filepath.lastIndexOf("/"); String filename = filepath.substring(index,filepath.length()); filepath = filepath.substring(0, index+ 1); file = new File(filepath); file.mkdirs(); // 创建文件 File newFile = new File(filepath,filename); newFile.createNewFile(); return true; } } if(filepath.contains("\\")){ if(filepath.contains("/")){ throw new RuntimeException("路径不合法"); }else { // e:\\a\\b\\c\\a.txt int index = filepath.lastIndexOf("\\"); String filename = filepath.substring(index,filepath.length()); filepath = filepath.substring(0, index+ 1); file = new File(filepath); file.mkdirs(); // 创建文件 File newFile = new File(filepath,filename); newFile.createNewFile(); return true; } } throw new RuntimeException("路径不合法"); } public static void main(String[] args) { try { createDirAndFile("d:\\a\\b\\c\\a.txt"); // 路径 System.out.println("文件创建成功..."); } catch (IOException e) { e.printStackTrace(); } } }
5、其他常见命令
①判断文件是否已经存在---file. exists()
②判断是否是文件夹(目录) ---file. isDirectory()
③判断是否是文件---file. isFile()
④判断是否是隐藏文件---file. isHidden()
⑤判断是否是绝对路径---file. isAbsolute()
绝对路径:以盘符开头,比如: e:/aaa. txt是绝对路径,aaa. txt不是绝对路径。
相对路径:相对于当前工程,没有指定的盘符开头
package com.jr.afternoon; import org.junit.Test; import java.io.File; import java.util.ArrayList; import java.util.Arrays; public class Ch04 { @Test // 判断文件是否已经存在---file.exists() public void test1() { File file = new File("e:/aaa.txt"); System.out.println(file.exists()); } @Test // 判断文件是否已经存在---file.exists() //判断是否是文件夹(目录)---file.isDirectory() // 判断是否是文件---file.isFile() // 判断是否是隐藏文件---file.isHidden() // 判断是否是绝对路径---file.isAbsolute() // 绝对路径:以盘符开头,比如 :e:/aaa.txt是绝对路径,aaa.txt不是绝对路径。 //相对路径:相对于当前工程,没有指定的盘符开头 public void test2() { File file = new File("e:/aaa.txt"); System.out.println(file.isAbsolute()); System.out.println(file.isDirectory()); System.out.println(file.isFile()); System.out.println(file.isHidden()); } // 文件列表的操作 @Test public void test3() { File file = new File("E:\\jiruan\\workplace"); // 拿到当前目录下的所有文件名---file.list(); String[] fileNames = file.list(); System.out.println(Arrays.toString(fileNames)); // 拿到当前目录下的所有对象---file.list(); } @Test public void test4() { File file = new File("E:\\jiruan\\workplace"); // 拿到当前目录下的所有对象---file.list(); File[] files = file.listFiles(); System.out.println(Arrays.toString(files)); } }