0%

单列集合图解


注意点:

  1. List系列集合:有序、可重复、有索引
  2. Set系列集合:无序、不重复、无索引
  3. Vector集合已经被淘汰,了解即可
  4. Collection接口是单列集合的祖先(最顶层),它的功能所有单列集合都可以使用
  5. 切记:泛型只允许指定“引用数据类型”,当集合需要存储基本数据类型时,我们可以在泛型中指定基本数据类型对应的包装类
    1
    2
    // 集合指定基本数据类型的包装类
    Collection<Integer> collection = new ArrayList<>();

Collection接口

常用方法
1
2
3
4
5
6
public boolean add(E e)                 把给定的对象添加到当前集合中
public void clear() 清空集合中所有的元素
public boolean remove(Object e) 把给定的对象在当前集合中删除
public boolean contains(Object obj) 判断当前集合中是否包含给定的对象
public boolean isEmpty() 判断当前集合是否为空
public int size() 返回集合中元素的个数/集合的长度

例题:

  1. add():将给定的对象添加到当前集合中
    1
    2
    3
    4
    // 定义集合
    Collection<String> collection = new ArrayList<>();
    // 添加元素
    boolean success = collection.add("张三");
    注意:
    a. add()的返回值:true,表示添加成功,false,表示添加失败
    b. 如果当前集合是List系列的,则返回值一定是true(一定会添加成功)
    c. 如果当前集合是Set系列的,则返回值有可能是true,也有可能是false
    原因:Set集合是不重复的,当指定添加的元素在集合中存在,则添加失败,add()的返回值就是false
  2. clear():清空集合
    1
    2
    3
    4
    5
    6
    7
    // 定义集合
    Collection<String> collection = new ArrayList<>();
    // 添加元素
    boolean success = collection.add("张三");
    boolean success = collection.add("李四");
    // 清空集合
    collection.clear()
  3. remove(E e):删除集合中指定的元素
    1
    2
    3
    4
    5
    6
    // 定义集合
    Collection<String> collection = new ArrayList<>();
    // 添加元素
    boolean success = collection.add("张三");
    // 删除集合中指定的元素
    boolean resultRemove = collection.remove("张三");
    注意:
    a. 如果当前集合中没有指定删除的元素,则删除失败,返回值为:false
    b. 如果当前集合中有指定删除的元素,则删除成功,返回值为:true
    c. remove()的实参一定是对象(不能是索引)

    原因:Collection接口中的方法声明的是单列集合(Set + List)中共性的方法,>Set系列集合是没有索引的,所以如果在Collection中声明有索引的方法是不合适的

    补充说明:List集合有索引、Set集合无索引,所以有索引的方法是List集合的特有方法,会被声明在List接口中

  4. contains():判断当前集合中是否包含给定的对象
    注意点: 如果当前集合存储的数据是自定义类,此时使用contains()判断集合中是否包含给定的对象,自定义类需要重写equals()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.util.Objects;

public class Student {
private String name;
private int age;

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public Student() {
}

public void setName(String name) {
this.name = name;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}
// 不用手写,直接在IDEA中,按快捷键 alt + insert,然后选择重写equals即可
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
// 集合存储自定义对象
Collection<Student> collection02 = new ArrayList<>();
// 创建自定义对象(准备数据测试)
Student student01 = new Student("张飞",18);
Student student02 = new Student("曹操",20);
Student student03 = new Student("张飞",18);
// 将元素添加到集合中
collection02.add(student01);
collection02.add(student02);
// Student未重写equals方法,返回子:fasle
boolean result01 = collection02.contains(student03);
// Student重写了equals方法,返回子:true
boolean result01 = collection02.contains(student03);

为什么要重写equals()

  1. Object是所有类的父类,equals()方法是声明定义在Object中的
  2. Object中的equals比较的是栈内存中的值,即:基本数据类型比较其值,引用数据类型比较的是地址值
  3. String类中的equals重写了,所以字符串调用equals比较的是 堆内存 中 存储的具体值,而不是栈内存中的地址值
  4. 自定义类,如果想要比较其属性中存储的值是否相等,则需要重写equals,否则equals()是Object继承下来的方法,比较的是地址值
  5. 技巧:重写的代码不用书写,IDEA可以自动生成(alt + insert,然后选择重写的方法equals即可)

isEmpty():判断当前集合是否是空集合

1
2
3
4
Collection<String> collection = new ArrayList<>();
// 当前集合是空集合,则返回:true
// 不是空集合,返回:false
boolean issuccess = collection.isEmpty();

size():获取集合中的元素个数

1
2
3
Collection<String> collection = new ArrayList<>();
// 获取集合元素个数
int len = collection.size();
Collection遍历(单列集合通用遍历方式)

Collection集合的遍历方式有三种:迭代器遍历,增强for、lambda
注意:这三种方式的遍历,都不允许在集合遍历时,使用集合中的方法对集合进行添加、删除等操作

  1. 迭代器遍历集合
    迭代器是Java中专门用来遍历集合的
    1
    2
    3
    4
    5
    6
    7
    public Iterator<E> iterator()       // Collection接口中的方法,用来获取迭代器对象

    // Iterator中的方法
    // 判断当前指针所在位置是否有元素,有元素,返回true,没有,返回false
    public boolean hasNext();
    // 获取迭代器指针所在位置的元素,并且将指针向后移动一个位置
    public E next();
    注意:
    a. 当我们获取一个新的迭代器对象时,迭代器指针此时的位置是在第一个元素上
    b. 当指针所在的位置,没有元素,此时使用next(),程序会抛出错误(所以在使用next获取元素之前一定要,判断指针所在位置是否有元素)
    c. 迭代器遍历完成后,指针不会复位(遍历开始时的初始位置)
    d. 迭代器遍历时,不能使用集合中的方法,对集合进行添加、删除操作(可以使用迭代器方法删除、添加)
    技巧:由于迭代器遍历完成后,指针不会复位,如果此时还想再次遍历集合,可以创新创建一个新的迭代器对象,再进行遍历
    例题:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 创建集合对象
    Collection<String> collection = new ArrayList<>();
    // 添加数据
    collection.add("张三");
    collection.add("李四");

    // 获取迭代器对象
    Iterator<String> iterator = collection.iterator();
    // 迭代器遍历集合
    while(iterator.hasNext()){
    String item = iterator.next();
    System.out.println(item);
    }
    迭代器遍历集合时,不能使用集合中的方法删除、添加元素,但可以使用迭代器中的方法添加、删除元素
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 创建集合对象
    Collection<String> collection = new ArrayList<>();
    // 添加数据
    collection.add("张三");
    collection.add("李四");
    Iterator<String> iterator = collection.iterator();
    while(iterator.hasNext()){
    String item = iterator.next();
    if(item.equals("张三")) {
    // 从底层集合中删除此迭代器 返回的最后一个元素
    iterator.remove();
    }
    System.out.println(item);
    }
  2. 增强for遍历

    a. 增强for是JDK5出现的语法
    b. 增强for的底层实现就是一个迭代器
    c. 增强for遍历时,也是不能使用集合中的方法对集合进行添加、删除操作(原因:底层是迭代器)
    d. 所有的 “单列集合” 以及 “数组” 才可以使用增强for遍历
    格式:for(元素类型 变量名 : 集合/数组) {}
    例题:

    1
    2
    3
    4
    5
    6
    Collection<String> collection = new ArrayList<>();
    collection.add("张三");
    collection.add("李四");
    for(String item : collection) {
    System.out.println(item);
    }
  3. lambda
    lambda是为了简化匿名内部类而出现的新语法(JDK8)
    例题:
    准备数据
    1
    2
    3
    4
    Collection<String> collection = new ArrayList<>();
    collection.add("张飞");
    collection.add("孙权");
    collection.add("诸葛亮");
    匿名内部类的方式遍历(forEach + 匿名内部类)
    1
    2
    3
    4
    5
    6
    7
    // Consumer:函数式接口
    collection.forEach(new Consumer<String>() {
    @Override
    public void accept(String s) {
    System.out.println(s);
    }
    });
    lambda方式遍历(lambda + forEach
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // forEach + Lambda 遍历集合
    collection.forEach((String s) -> {
    System.out.println(s);
    });

    // 简化:如果需要重写的方法只有一个参数,则可以将()去掉
    collection.forEach(s -> {
    System.out.println(s);
    });

    // 再次简化:如果方法体中只有一条语句,则可以将{}去掉
    collection.forEach(s -> System.out.println(s));
    注意:在遍历时,也是不能通过集合中的方法对集合中的元素进行添加、删除操作的

List集合

a. List是Collection接口的子接口
b. 特点:有序、有索引、可重复
c. List集合是有索引的,所以在List接口中声明了一系列操作索引的特有方法

List中的特有方法
1
2
3
4
5
6
void add(int index,E element)       集合指定位置插入元素
E remove(int index) 删除指定索引处的元素,并返回删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素(修改前的值)
E get(int index) 返回指定索引处的元素

注意:索引是从0开始的

例题:

1
2
3
4
5
6
List<String> list = new ArrayList<>();
list.add("赵四");
list.add("刘能");
list.add("谢广坤");
// 删除索引0处的元素
list.remove(0);

remove()的特殊用例(重要):

1
2
3
4
boolean remove(Object object)       继承自Collection接口
E remove(int index) List接口中定义的方法

remove(int index)和remove(Object object)属于重载方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(20);
list.add(30);
// 当List集合中存储的数据是Integer类型的数据时,此时我们我们传入一个整数
// 为什么调用的是remove(int index),而不是remove(Object object)呢?
Integer removeElement = list.remove(1);

// remove的执行机制:据传入的 参数的类型 进行判断选择哪种remove方法
// 如:我们传入的参数是int类型,则是选择remove(int index)
// 当我们传入的参数是 Integer(引用数据类型),则选择remove(Object object)

// 手动装箱
Integer i = Integer.valueOf(1);
// 选择的是remove(Object object)
boolean success = list.remove(i);

简单理解:参数是基本数据类型,优先选择remove(int index),参数是引用数据类型,优先选择remove(Object object)

List集合特有遍历方式
1
2
1. 列表迭代器
2. 普通for遍历

列表迭代器遍历

a. ListIterator:列表迭代器,是一个接口,继承Iterator
b. ListIterator接口在继承了Iterator接口中的方法继承上,还自定义了一些特有方法,如:add()

例题:

1
2
3
4
5
6
7
8
9
10
11
12
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
// 获取ListIterator对象
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
String str = listIterator.next();
if (str.equals("c")) listIterator.add("e"); // 添加元素
System.out.println(str);
}
System.out.println(list);

普通for遍历

1
2
3
4
5
6
7
8
9
10
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
// 普通for遍历:
for (int i = 0; i < list.size(); i++) {
// List集合是有索引的,所以可以通过索引获取对应值
String str = list.get(i);
System.out.println(str);
}
ArrayList
  1. ArrayList是List接口的实现类
  2. ArrayList的数据结构:数组结构
  3. ArrayList的底层原理:
    a. 利用空参构造创建的集合,在底层创建一个默认长度为0的数组
    b. 当添加第一个元素时,底层会创建一个新的长度为10的数组
    c. 当数组存满时,会扩容当前数组长度1.5倍(创建长度为1.5倍的新数组,再将原本数组拷贝到新数组中)
    d. 依次类推,数组存满就扩容当前数组长度的1.5倍,再将原数组拷贝到新数组中
    e. 特殊情况:如果一次添加多个元素,且数组的1.5倍还是放不下,则创建的新数组的长度以实际元素个数为准

注意:size():获取集合内元素的个数,并不是底层数组的长度
AraryList无特殊的API,与List接口中定义的基本一致

LinkedList
  1. LinkedList是List接口的实现类
  2. 底层数据结构是双链表,查询慢,增删快,但是如果是操作首尾元素,速度也很快
  3. LinkedList无特殊的API,基本上都是实现List接口中的方法

LinkedList特有方法

1
2
3
4
5
6
7
8
由于LinkedList操作首尾元素的数据很快,所以在LinkedList中定义了自己特有的API操作首尾元素

public void addFirst(E e) 在列表开头插入指定元素
public void addLast(E e) 在列表末尾插入指定的元素
public E getFirst() 获取列表中的首元素
public E getLast() 获取列表中的尾元素
public E removeFirst() 删除列表中的首元素,并返回被删除的元素
public E removeLast() 删除列表中的尾元素,并返回被删除的元素

Set集合

  1. Set是一个接口,Collection的子接口
  2. Set集合:无序、不重复、无索引
  3. Set集合没有特殊的API,基本上都是从Collection继承下来API
  4. Set集合也没有特殊的遍历方式(迭代器、增强for、lambda)

由于Set集合是不重复的,所以当使用add()添加元素时,可能会添加失败

1
2
3
4
5
6
add():当集合中存在指定的元素,则添加失败,返回false
当集合中不存在指定的元素,则添加成功,返回true

Set<String> set = new HashSet<>();
boolean bool01 = set.add("张三"); // true
boolean bool02 = set.add("张三"); // false
HashSet
  1. Set接口的实现类
  2. 无特殊API,基本上与Set中的API一致
  3. HashSet底层采取 哈希表 存储数据
  4. 哈希表是一种对于 增删改查 数据性能都比较好的一种结构
  5. 无序、不重复、无索引

哈希表

  1. 哈希表的组成:
    JDK8之前:数组 + 链表
    JDK8开始:数组 + 链表 + 红黑树
  2. 哈希值:
    根据hashCode方法算出来的int类型的整数
    该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算
    一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值
  3. 对象的哈希值特点:
    如果没有重写hashCode方法,不同的对象(地址值)计算出来的哈希值是不同的
    如果已经重写hashCode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
    在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样(哈希碰撞)
  4. 重写hasCode():IDEA中快捷键 alt + insert,然后选择重写hasCode()即可(IDEA会生成重写代码)

HashSet底层原理:

  1. JDK8以前底层原理:
    a. 创建一个默认长度16,默认加载因子为0.75的数组,数组名为tab的数组
        加载因子:当集合中存入的元素个数达到了 当前数组长度的 0.75倍时,此时数组的长度会扩容到当前数组的两倍
        如:当前数组长度为:16,加载因子为:0.75
        当集合中元素个数达到了 16 * 0.75 = 12 个时,数组扩容
        现在数组长度:16 * 2 = 32
    b. 根据元素的 哈希值 和 数组的长度 计算出该元素应存入的位置
    c. 判断当前位置是否为null
        如果是null直接存入
        如果位置不为null,表示该位置有元素了,则调用equals方法比较属性值
            一样:不存入
            不一样:存入数组,形成链表
            JDK8以前:新元素存入数组,老元素挂在新元素的下面
            JDK8以后,新元素直接挂在老元素下面
            当链表长度大于8,且数组长度大于等于64时,此时大于8的链表就会转成 红黑数 数据结构

注意:如果集合存储的是自定义对象,则自定义类中 要重写 hashCode 和 equals方法

原因:

  1. HashSet集合在存储数据时,需要用hashCode()计算哈希值,如果没有重写hashCode(),则hashCode()根据地址值计算哈希值,无法根据对象的属性值计算哈希值
  2. HashSet集合在存储数据时,需要使用equals()方法判断数组内的元素是否和当前存入元素是否相等,如果没有重写equals(),则根据地址值判断,重写了则是堆内存中的具体值比较
LinkedHashSet

特点:有序、不重复、无索引
底层结构:哈希表(与HashSet底层基本一致,区别:每个元素又额外的多了一个双链表的机制记录存储的顺序)

TreeSet

特点:可排序、不重复、无索引

  1. 底层数据结构:红黑树
  2. Java中,预定义类(String、Double、Integer等等)都是有实现Comparable接口的
  3. 默认排序规则:
        a.数值型:默认按照从小到大的顺序排序
        b.字符、字符串:按照字符在ASCII表中的数字升序排序
  4. 指定排序规则
        方式一:JavaBean类实现Comparable接口指定的比较规则
        方式二:创建TreeSet对象的时候,传递比较器Comparator指定规则
        注意:当类中实现了Comparable接口指定排序规则了,此时创建TreeSet对象时,又传入了Comparator指定排序规则,此时会优先使用创建对象时,传入的比较规则
        注意:Comparable与Comparator都是比较器:可以查阅资料,了解它们的区别

例题:
当集合存储的数据是自定义类,则自定义类要实现Comparable接口,指定排序规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class Person implements Comparable<Person>{
public String name;
public int age;

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

// 重写比较规则的方法
@Override
public int compareTo(Person o) {
// 一定要知道:TreeSet底层是 红黑数的数据结构,所以要知道红黑树是如何存数据和取数据的
// 才能理解

// 使用add 添加元素时,会调用 compareTo方法
// 根据compareTo比较规则,将元素添加到对应的位置
// 比较对象:
// 当前添加的元素 与 集合中存在的元素 比较
// compareTo的返回值:
// 正数:表示当前添加的元素大,存在元素(集合中存在的)节点的右边
// 负数:表示当前元素小,存在元素(集合中存在的)节点的左边
// 0:表示在集合中已经存在该元素,添加失败


/*
* this:当前添加的元素
* o:已经在集合中存在的元素
* 返回值:
* 负数:表示当前元素小,存在元素(集合中存在的)节点的左边
* 正数:表示当前添加的元素大,存在元素(集合中存在的)节点的右边
* 0:表示在集合中已经存在该元素,添加失败
* 注意:
* 在比较大小时,会多次调用该方法,直到找到 元素存储的位置(节点)
* */
// 按年龄比较
int result = this.getAge() - o.getAge();
return result;
}
public Person() {
}

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

TreeSet创建对象时,传入比较器指定比较规则

1
2
3
4
5
6
7
8
9
10
11
12
TreeSet<String> treeSet2 = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// o1:当前添加的元素
// o2:集合中存在的元素
// 根据字符串长度比较大小
int result = o1.length() - o2.length();
// 如果长度为0,则调用默认的比较方法比较
if (result == 0) return o1.compareTo(o2);
return result;
}
});

集合使用场景

  1. 如果想要集合中的元素 可重复,建议使用ArrayList集合,基于数组的,ArrayList也是使用的最多的集合
  2. 如果想要集合中的元素 可重复 且 当前的 增删 操作 明显多于 查询操作,用LinkedList集合,基于链表
  3. 如果想对集合中的元素 去重,用HashSet集合,基于哈希表的,HashSet用的也比较多
  4. 如果想对集合中的元素去重,而且保证 存取顺序,用LinkedHashSet集合,基于哈希表和双链表,效率低于HashSet
  5. 如果想对集合中的元素进行 排序,用TreeSet集合,基于红黑树

概述

1、表示一个路径,可以是文件的路径,也可以是文件夹的路径
2、这个路径可以是存在的,也允许是不存在的

File对象的作用

a. 表示一个路径
b. 可以通过调用File类中定义的方法,操作本地文件或目录

构造函数

1
2
3
4
5
6
7
8
根据文件路径字符串创建文件对象
pulbic File(String pathname)

根据父路径字符串和子路径字符串创建文件对象(pathname + child拼接后,再创建对象)
public File(String pathname,String child)

根据父路径 文件对象 和子路径字符串创建文件对象
public File(File parent,String child)

注意:由于File本身是表示一个路径,所以我们不能使用无参构造函数创建File对象
例题:

1
2
3
4
5
6
7
8
9
10
// 路径字符串
File file01 = new File("E:\\Users\\C\\Desktop\\a.txt");

// 父路径 + 子路径 拼接
File file02 = new File("E:\\Users\\C\\Desktop","a.txt");

// 父路径文件对象 + 子路径字符串 拼接
File file03 = new File("E:\\Users\\C\\Desktop"); // 父路径 文件对象
File file04 = new File(file03,"a.txt"); // 父路径文件对象 + 子路径字符串

File中常用方法

1
2
3
4
5
6
7
8
public bool isDirectory()           判断是否是文件夹
public bool isFile() 判断是否是文件
public bool exits() 判断File表示的路径是否存在
public long length 返回文件的大小(字节数量)
public String getAbsolutePath() 返回文件的绝对路径
public String getPath() 返回定义文件时使用的路径
public String getName() 返回文件的名称,带后缀
public long lastModified() 返回文件的最后修改时间(时间毫秒值)

例题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
File file = new File("D:\\Lenovo\\桌面\\a.txt");
// 1. 判断是否是文件夹
boolean bool01 = file.isDirectory();
System.out.println(bool01);

// 2. 判断是否是文件
boolean bool02 = file.isFile();
System.out.println(bool02);

// 3. 判断File表示的路径是否存在
boolean bool03 = file.exists();
System.out.println(bool03);

// 4. 获取文件的大小(字节数)
// 注意:
// length()只能获取 文件的 大小,不能获取文件的大小
// 如果想获取文件夹的大小,则需要将文件夹内的所有文件的大小相加即可
long size = file.length();
System.out.println(size);

// 5. 返回文件的绝对路径
String path = file.getAbsolutePath();
System.out.println(path);

// 6. 返回定义文件时使用的路径
String path02 = file.getPath();
System.out.println(path02);

// 7. 返回文件名
// 注意:如果是文件,则会带上文件的后缀名,如果是文件夹,则会直接返回文件夹的名字
String fileName = file.getName();
System.out.println(fileName);

// 8. 返回文件最后修改的时间
long date = file.lastModified();
System.out.println(date);

创建和删除的方法

1
2
3
4
public boolean createNewFile()     创建一个空的文件夹
public boolean mkdir() 创建单个文件夹
public boolean mkdirs() 创建多级文件夹
public boolean delete() 删除文件,空文件夹

例题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 File file01 = new File("D:\\Lenovo\\桌面\\b.txt");

// 1. 创建空文件
// 返回值:创建文件是否成功
// 当路径表示的文件存在,则创建失败,返回false
// 当路径表示的路径不存在,则创建成功,返回true
// 当路径是错误的(如:父级路径不存在),则程序直接抛出异常

// 注意:createNewFile创建的一定是文件,当给的路径是没有后缀名的,则会创建一个没有后缀名的文件
boolean bool01 = file01.createNewFile();
System.out.println(bool01);

// 2. 创建目录
// 注意:
// 1. 当创建的文件夹,存在则创建失败,返回false
// 2. mkdir只能创建单级文件夹,不能创建多级文件夹(父级目录也不存在)
// 3. 父级目录不存在时,创建文件夹失败,返回false,程序不会抛出异常
File file02 = new File("D:\\Lenovo\\桌面\\ee\\ff");
boolean bool02 = file02.mkdir();
System.out.println(bool02);

// 3. 创建多级文件夹(既能创建单级目录,也可以创建多级目录)
File file03 = new File("D:\\Lenovo\\桌面\\ee\\ff");
boolean bool03 = file03.mkdirs();
System.out.println(bool03);

// 4. 删除文件 或 空文件夹()
File file04 = new File("D:\\Lenovo\\桌面\\b.txt");
boolean bool04 = file04.delete();
System.out.println(bool04);
// 如果删除的目录,不是空的,则删除失败,返回false
File file05 = new File("D:\\Lenovo\\桌面\\ee\\ff");
boolean bool05 = file05.delete();
System.out.println(bool05);

// 注意:delete只能删除 文件 和 空文件夹 不走回收站

获取路径下的所有文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
获取目录下的文件,并进行遍历
方法:
public File[] listFiles() 获取当前路径下的所有内容
注意:
1. 当路径不存在时,则返回null
2. 当路径表示的是文件时,返回null
3. 当路径表示的是一个空文件夹时,则返回一个长度为0的数组
4. 当路径是一个有内容的文件夹时,则返回文件夹内的所有文件和文件夹(数组的形式返回)
5. 当路径是一个 “隐藏文件夹” 时,则会将文件夹和文件(包括隐藏文件)全部返回(以数组的形式)
6. 当路径是一个 “需要权限”的文件夹时,则返回null


其他方法:
listRoots()、list()、list(FilenameFilter filter)、listFiles(FileFilter filter)、
listFiles(FilenameFilter filter)

例题:
listFiles():获取路径下的所有内容(文件/文件夹)

1
2
3
4
5
6
7
8
9
10
File file = new File("D:\\Lenovo\\桌面\\ee");
File[] files = file.listFiles();
// 遍历并删除
for (File file1 : files) {
// 在删除之前应该要判断是否是文件还是文件夹
// 原因:delete只能删除空文件夹,所以要做特殊处理
// 这里没有做判断,是因为测试时,目录全是空的
boolean bool = file1.delete();
System.out.println(bool);
}

listRoots():静态方法,获取系统中的所有盘符

1
File[] arr = File.listRoots();

list():获取当前路径下的所有内容(只能获取文件名称/文件夹名称)

1
2
3
4
5
// 如果是文件夹,则是文件夹名,如果是文件,则是文件名(有后缀)
// 与listFiles()的区别:
// list只能获取文件名,而listFiles获取到的是完整的路径
File file01 = new File("D:\\Lenovo\\桌面\\ee");
String[] strings = file01.list();

list(FilenameFilter filter):利用文件名过滤,获取当前路径下的所有内容

1
2
3
4
5
6
7
8
9
10
11
12
13
// FilenameFilter:函数式接口
String[] strings1 = file01.list(new FilenameFilter() {
/*
* dir:父级路径
* name:文件名(没有路径,仅仅是名字)
* 返回值:true,则表示满足条件,保留,如果false,则当前文件舍弃
* */
@Override
public boolean accept(File dir, String name) {
// 所有的内容都舍弃
return false;
}
});

基本概念

  1. 并发:在同一时刻,有多个指令在单个CPU上交替执行
  2. 并行:在同一时刻,有多个指令在多个CPU上同时执行

多线程的实现方式

多线程的实现方式有三种:继承Thread、实现Runable、实现Callable

第一种:继承Thread

实现步骤:
    a. 自定义类,继承Thread类
    b. 重写run方法
    c. 创建自定义类对象,并启动线程

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyThread extends Thread{
@Override
public void run() {
// 编写线程执行的代码
for (int i = 0; i < 10; i++) {
System.out.println(getName());
}
}
}

class Test {
MyThread myThread = new MyThread();
}