JAVA笔记:集合、Collection

1、内容

1.1、集合与数组的区别,缓存的管理,Collection 、List、Set 接 口的作用及相关的子类
1.1.1、类集设置的目的(重点)
对象数组有那些问题?普通的对象数组的最大问题在于数组中的元素个数是固定的,不能动态的扩充大小,所以最早的时候可以通过链表实现一个动态对象数组。但是这样做毕竟太复杂了,所以在 Java 中为了方便用户操作各个数据结构,所以引入了类集的概念,有时候就可以把类集称为 java 对数据结构的实现。

在整个类集中的,这个概念是从 JDK 1.2(Java 2)之后才正式引入的,最早也提供了很多的操作类,但是并没有完整的提出类集的完整概念。

类集中最大的几个操作接口:Collection、Map、Iterator,这三个接口为以后要使用的最重点的接口。

所有的类集操作的接口或类都在 java.util 包中。

在这里插入图片描述

1.1.2、、Collection 接口(重点)

Collection 接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。 此接口定义在 java.util 包中。 此接口定义如下:

public interface Collection<E> extends Iterable<E>

此接口使用了泛型技术,在 JDK 1.5 之后为了使类集操作的更加安全,所以引入了泛型。 此接口的常用方法如下所示

在这里插入图片描述

本接口中一共定义了 15 个方法,那么此接口的全部子类或子接口就将全部继承以上接口中的方法。
但是,在开发中不会直接使用 Collection 接口。而使用其操作的子接口:List、Set。
之所以有这样的明文规定,也是在 JDK 1.2 之后才有的。一开始在 EJB 中的最早模型中全部都是使用 Collection 操作
的,所以很早之前开发代码都是以 Collection 为准,但是后来为了更加清楚的区分,集合中是否允许有重复元素所以 SUN
在其开源项目 —— PetShop(宠物商店)中就开始推广 List 和 Set 的使用。

2、List 接口(重点)

在整个集合中 List 是 Collection 的子接口,里面的所有内容都是允许重复的。 List 子接口的定义:

public interface List<E> extends Collection<E>

此接口上依然使用了泛型技术。此接口对于 Collection 接口来讲有如下的扩充方法:

set,Array等通用

在这里插入图片描述

在 List 接口中有以上 10 个方法是对已有的 Collection 接口进行的扩充。 所以,证明,List 接口拥有比 Collection 接口更多的操作方法。 了解了 List 接口之后,那么该如何使用该接口呢?需要找到此接口的实现类,常用的实现类有如下几个: · ArrayList(95%)、Vector(4%)、LinkedList(1%)

2.1、Array类

1、但凡array调用add,那返回的一定是true,失败也是true

在这里插入图片描述

import java.util.ArrayList;

public class Demo1 {

    public static void main(String[] args){
        //ArrayList:    使用的是数组结构,对于增加删除慢,查找快
        //默认长度为:10
        ArrayList<Integer> data = new ArrayList<>();//
        data.add(100);
    }
}
2.1.1、方法:
1、get
public static Object get​(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
返回指定数组对象中索引组件的值。 如果对象具有基本类型,则该值自动包装在对象中。 
参数 
array - 数组 
index - 索引 
结果 
指定数组中索引组件的(可能包装的)值 
异常 
NullPointerException - 如果指定的对象为null 
IllegalArgumentException - 如果指定的对象不是数组 
ArrayIndexOutOfBoundsException - 如果指定的 index参数为负数,或者它大于或等于指定数组的长度 

Code:

import java.lang.reflect.Array;
import java.util.ArrayList;

public class Demo1 {

    public static void main(String[] args){
        //ArrayList:    使用的是数组结构,对于增加删除慢,查找快
        ArrayList<Integer> data = new ArrayList<>();
        data.add(100);
        data.add(200);
        data.add(300);
        System.out.println(data.get(1));
    }
}
//200
2、newInstance
public static Object newInstance​(类<?> componentType, int length) throws NegativeArraySizeException
创建具有指定组件类型和长度的新数组。 调用此方法等效于创建数组,如下所示: 
 int[] x = {length};
 Array.newInstance(componentType, x);
 新阵列的尺寸数不得超过255。 

参数 
componentType - 表示新阵列的组件类型的 类对象 
length - 新阵列的长度 
结果 
新阵列 
异常 
NullPointerException - 如果指定的 componentType参数为null 
IllegalArgumentException - 如果componentType为 Void.TYPE,或者请求的阵列实例的维数超过255。 
NegativeArraySizeException - 如果指定的 length为负数 

3、getLength
public static int getLength​(Object array) throws IllegalArgumentException
返回指定数组对象的长度,如 int 。 
参数 
array - 数组 
结果 
数组的长度 
异常 
IllegalArgumentException - 如果object参数不是数组 

4、getBoolean
public static boolean getBoolean​(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
返回指定数组对象中索引组件的值,如 boolean 。 
参数 
array - 数组 
index - 该指数 
结果 
指定数组中索引组件的值 
异常 
NullPointerException - 如果指定的对象为null 
IllegalArgumentException - 如果指定的对象不是数组,或者索引元素无法通过标识或扩展转换转换为返回类型 
ArrayIndexOutOfBoundsException - 如果指定的 index参数为负数,或者它大于或等于指定数组的长度 
5、getByte
public static byte getByte​(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
返回指定数组对象中索引组件的值,如 byte 。 
参数 
array - 数组 
index - 该指数 
结果 
指定数组中索引组件的值 
异常 
NullPointerException - 如果指定的对象为null 
IllegalArgumentException - 如果指定的对象不是数组,或者索引元素无法通过标识或扩展转换转换为返回类型 
ArrayIndexOutOfBoundsException - 如果指定的 index参数为负数,或者它大于或等于指定数组的长度 
6、getChar
public static char getChar​(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
返回指定数组对象中索引组件的值,如 char 。 
参数 
array - 数组 
index - 该指数 
结果 
指定数组中索引组件的值 
异常 
NullPointerException - 如果指定的对象为null 
IllegalArgumentException - 如果指定的对象不是数组,或者索引元素无法通过标识或扩展转换转换为返回类型 
ArrayIndexOutOfBoundsException - 如果指定的 index参数为负数,或者它大于或等于指定数组的长度 

7、getShort
public static short getShort​(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
返回指定数组对象中索引组件的值,如 short 。 
参数 
array - 数组 
index - 该指数 
结果 
指定数组中索引组件的值 
异常 
NullPointerException - 如果指定的对象为null 
IllegalArgumentException - 如果指定的对象不是数组,或者索引元素无法通过标识或扩展转换转换为返回类型 
ArrayIndexOutOfBoundsException - 如果指定的 index参数为负数,或者它大于或等于指定数组的长度 

8、getInt
public static int getInt​(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
返回指定数组对象中索引组件的值,如 int 。 
参数 
array - 数组 
index - 该指数 
结果 
指定数组中索引组件的值 
异常 
NullPointerException - 如果指定的对象为null 
IllegalArgumentException - 如果指定的对象不是数组,或者索引元素无法通过标识或扩展转换转换为返回类型 
ArrayIndexOutOfBoundsException - 如果指定的 index参数为负数,或者它大于或等于指定数组的长度 

9、getLong
public static long getLong​(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
返回指定数组对象中索引组件的值,如 long 。 
参数 
array - 数组 
index - 索引 
结果 
指定数组中索引组件的值 
异常 
NullPointerException - 如果指定的对象为null 
IllegalArgumentException - 如果指定的对象不是数组,或者索引元素无法通过标识或扩展转换转换为返回类型 
ArrayIndexOutOfBoundsException - 如果指定的 index参数为负数,或者它大于或等于指定数组的长度 
10、getFloat
public static float getFloat​(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
返回指定数组对象中索引组件的值,如 float 。 
参数 
array - 数组 
index - 该指数 
结果 
指定数组中索引组件的值 
异常 
NullPointerException - 如果指定的对象为null 
IllegalArgumentException - 如果指定的对象不是数组,或者索引元素无法通过标识或扩展转换转换为返回类型 
ArrayIndexOutOfBoundsException - 如果指定的 index参数为负数,或者它大于或等于指定数组的长度 

11、getDouble
返回指定数组对象中索引组件的值,如 double 。 
参数 
array - 数组 
index - 索引 
结果 
指定数组中索引组件的值 
异常 
NullPointerException - 如果指定的对象为null 
IllegalArgumentException - 如果指定的对象不是数组,或者索引元素无法通过标识或扩展转换转换为返回类型 
ArrayIndexOutOfBoundsException - 如果指定的 index参数为负数,或者它大于或等于指定数组的长度 

12、set
public static void set​(Object array, int index, Object value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
将指定数组对象的索引组件的值设置为指定的新值。 如果数组具有基本组件类型,则首先自动解包新值。 
参数 
array - 数组 
index - 数组的索引 
value - 索引组件的新值 
异常 
NullPointerException - 如果指定的对象参数为null 
IllegalArgumentException - 如果指定的对象参数不是数组,或者数组组件类型是原始的并且解包转换失败 
ArrayIndexOutOfBoundsException - 如果指定的 index参数为负数,或者它大于或等于指定数组的长度 
//boolean等类型同理
2.1.2、ArrayList(重点)

ArrayList 是 List 接口的子类,此类的定义如下:

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable

此类继承了 AbstractList 类。AbstractList 是 List 接口的子类。AbstractList 是个抽象类,适配器设计模式。

package org.listdemo.arraylistdemo;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo01 {
	public static void main(String[] args) {
		List<String> all = new ArrayList<String>(); // 实例化List对象,并指定泛型类型
		all.add("hello "); // 增加内容,此方法从Collection接口继承而来
		all.add(0, "LAMP ");// 增加内容,此方法是List接口单独定义的
		all.add("world"); // 增加内容,此方法从Collection接口继承而来
		System.out.println(all); // 打印all对象调用toString()方法
	}
}

以上的操作向集合中增加了三个元素,其中在指定位置增加的操作是 List 接口单独定义的。随后进行输出的时候, 实际上调用的是 toString()方法完成输出的。

可以发现,此时的对象数组并没有长度的限制,长度可以任意长,只要是内存够大就行。

范例:进一步操作

· 使用 remove()方法删除若干个元素,并且使用循环的方式输出。

· 根据指定位置取的内容的方法,只有 List 接口才有定义,其他的任何接口都没有任何的定义。

import java.util.ArrayList;
import java.util.List;

public class Demo9 {
    public static void main(String[] args) {
        List<String> all = new ArrayList<String>(); // 实例化List对象,并指定泛型类型
        all.add("hello "); // 增加内容,此方法从Collection接口继承而来
        all.add(0, "LAMP ");// 增加内容,此方法是List接口单独定义的
        all.add("world"); // 增加内容,此方法从Collection接口继承而来
        all.remove(1); // 根据索引删除内容,此方法是List接口单独定义的
        all.remove("world");// 删除指定的对象
        System.out.print("集合中的内容是:");
        for (int x = 0; x < all.size(); x++) { // size()方法从Collection接口继承而来
            System.out.print(all.size() + "、"); // 此方法是List接口单独定义的
        }
    }

}
//集合中的内容是:1、

Code:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;

public class Demo4 {

    public static void main(String[] args){
        //Iterator
        //ListIterator
        ArrayList<Integer> data = new ArrayList<>();
        data.add(1);
        data.add(2);
        data.add(3);
        data.add(4);
        data.add(5);
        //Iterator<Integer> iterator = data.iterator();
        //按集合长度遍历
//        while (iterator.hasNext()){
        //指针下移
//            Integer i = iterator.next();
//            System.out.println(i);
//        }

        //iterator.next();
        //前无数据无法删除
        //iterator.remove();
        //System.out.println(data.size());
        //List双向,可向上移动
        ListIterator<Integer> iterator = data.listIterator();
        iterator.add(100);
        iterator.next();
        iterator.next();
        iterator.set(200);
        System.out.println(data.size());
        //位置向上移动
        //iterator.previous();
    }
}

拓展forEach
import java.util.ArrayList;

public class Demo5 {
    //forEach:增强for循环。最早出现在c#中
    //用于迭代数组 或 集合(Collection)
    public static void main(String[] args){
        int[] arr = {6,5,4,3,2,1};
       /* for (int i = 0;i < arr.length;i++){
            System.out.println(arr[i]);
        }*/
        for (int a : arr){
            System.out.println(a);
        }

        System.out.println("---------");
        ArrayList<String> data = new ArrayList<>();
        data.add("1");
        data.add("2");
        data.add("3");
        data.add("4");
        for (String s:data){
            System.out.println(s);
        }
    }
}

但是,这里需要注意的是,对于删除元素的操作,后面还会有更加清楚的讲解,此处只是简单的理解一下元素删除 的基本操作即可。具体的原理可以暂时不进行深入掌握。

//ArrayList:    使用的是数组结构,对于增加删除慢,查找快
2.2、Vector
与 ArrayList 一样,Vector 本身也属于 List 接口的子类,此类的定义如下:
public class Vector<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable,Serializable

此类与 ArrayList 类一样,都是 AbstractList 的子类。所以,此时的操作只要是 List 接口的子类就都按照 List 进行操作。

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class Demo9 {
    public static void main(String[] args) {
        List<String> all = new Vector<String>(); // 实例化List对象,并指定泛型类型
        all.add("hello "); // 增加内容,此方法从Collection接口继承而来
        all.add(0, "LAMP ");// 增加内容,此方法是List接口单独定义的
        all.add("world"); // 增加内容,此方法从Collection接口继承而来
        all.remove(1); // 根据索引删除内容,此方法是List接口单独定义的
        all.remove("world");// 删除指定的对象
        System.out.print("集合中的内容是:");
        for (int x = 0; x < all.size(); x++) { // size()方法从Collection接口继承而来
            System.out.print(all.get(x) + "、"); // 此方法是List接口单独定义的
        }

    }

}
//集合中的内容是:LAMP 、
以上的操作结果与使用 ArrayList 本身并没有任何的区别。因为操作的时候是以接口为操作的标准。

但是 Vector 属于 Java 元老级的操作类,是最早的提供了动态对象数组的操作类,在 JDK 1.0 的时候就已经推出了此类的使用,只是后来在 JDK 1.2 之后引入了 Java 类集合框架。但是为了照顾很多已经习惯于使用 Vector 的用户,所以在JDK 1.2 之后将 Vector 类进行了升级了,让其多实现了一个 List 接口,这样才将这个类继续保留了下来。
2.2.1、Vector 类和 ArrayList 类的区别(重点)
这两个类虽然都是 List 接口的子类,但是使用起来有如下的区别,为了方便大家笔试,列出此内容:

在这里插入图片描述

//ArrayList:    使用的是数组结构,对于增加删除慢,查找快
//Vector:   使用的也是数组结构,对于增加删除慢,查找快。
2.3、链表操作类:LinkedList(理解)

此类的使用几率是非常低的,但是此类的定义如下:

public class LinkedList<E> extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable

在这里插入图片描述

范例:验证 LinkedList 子类

import java.util.*;

public class Demo9 {
    public static void main(String[] args) {
            Queue<String> queue = new LinkedList<String>();
            queue.add("A");
            queue.add("B");
            queue.add("C");
            int len=queue.size();//把queue的大小先取出来,否则每循环一次,移除一个元素,就少
            //一个元素,那么queue.size()在变小,就不能循环queue.size()次了。
            for (int x = 0; x <len; x++) {
                System.out.println(queue.poll());
            }
            System.out.println(queue);

    }

}

Code:

import java.util.LinkedList;

public class Demo3 {

    public static void main(String[] args){
        //LinkedList   :    使用的是双向链表结构,对于增加删除快,查找慢
        //add
        //remove
        //get()
        LinkedList<Integer> data = new LinkedList<>();

        //data.addFirst(100)
        //data.addFirst(200)
        //Integer i = data.removeFirst();
        //System.out.println(i);
        //压栈
        data.push(100);
        data.push(200);

        //弹栈
        Integer i = data.pop();
        System.out.println(i);
    }
}

2.4、Set接口(重点)
set集合:值不能重复

Set 接口也是 Collection 的子接口,与 List 接口最大的不同在于,Set 接口里面的内容是不允许重复的。

Set 接口并没有对 Collection 接口进行扩充,基本上还是与 Collection 接口保持一致。因为此接口没有 List 接口中定义 的 get(int index)方法,所以无法使用循环进行输出。

那么在此接口中有两个常用的子类:HashSet、TreeSet

2.4.1、散列存放:HashSet(重点)

既然 Set 接口并没有扩充任何的 Collection 接口中的内容,所以使用的方法全部都是 Collection 接口定义而来的。

HashSet 属于散列的存放类集,里面的内容是无序存放的。

import java.util.*;

public class Demo9 {
    public static void main(String[] args) {
        Set<String> all = new HashSet<String>(); // 实例化Set接口对象
        all.add("A");
        all.add("B");
        all.add("C");
        all.add("D");
        all.add("E");
        System.out.println(all);

    }

}

使用 HashSet 实例化的 Set 接口实例,本身属于无序的存放。

那么,现在思考一下?能不能通过循环的方式将 Set 接口中的内容输出呢?

是可以实现的,因为在 Collection 接口中定义了将集合变为对象数组进行输出。

import java.util.*;

public class Demo9 {
    public static void main(String[] args) {

        Set<String> all = new HashSet<String>();
        all.add("A");
        all.add("B");
        all.add("C");
        all.add("D");
        all.add("E");
        Object obj[] = all.toArray();//将集合变为对象数组
        for(int x = 0; x < obj.length; x++){
            System.out.println(obj[x] + " ");
        }

    }

}

Code

import java.util.HashSet;
import java.util.Iterator;

public class Demo6 {
    //HashSet:散列存放(哈希表在学习HashMap集合时讲解)
    public static void main(String[] args){
        HashSet<String> set = new HashSet<>();
        set.add("1");
        set.add("2");
        set.add("3");
        set.add("4");
        Boolean f = set.add("1");//false
        System.out.println(f);
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}
2.4.2、、排序的子类:TreeSet(重点)

与 HashSet 不同的是,TreeSet 本身属于排序的子类,此类的定义如下:

public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, Serializable

下面通过代码来观察其是如何进行排序的。

import java.util.HashMap;
import java.util.Set;
import java.util.TreeSet;

public class Demo8 {

    public static void main(String[] args){

        Set<String> all = new TreeSet<String>();//实例化Set接口对象
        all.add("D");
        all.add("X");
        all.add("A");
        System.out.println(all);
    }
}
//A、D、X

} 虽然在增加元素的时候属于无序的操作,但是增加之后却可以为用户进行排序功能的实现。

2.4.3、排序的说明(重点)

定义Person:

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


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

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

    public Person() {
    }

    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 集合,向里面增加若干个 Person 对象。

import java.util.Set;
import java.util.TreeSet;

public class TreeSetPersonDemo01 {

    public static void main(String[] args){
        Set<Person> all = new TreeSet<Person>();
        all.add(new Person("张三",10));
        all.add(new Person("李四",10));
        all.add(new Person("王五", 11));
        all.add(new Person("赵六", 12));
        all.add(new Person("孙七", 13));
        System.out.println(all);
    }
}

此时的提示是:Person 类不能向 Comparable 接口转型的问题?

所以,证明,如果现在要是想进行排序的话,则必须在 Person 类中实现 Comparable 接口。

public class Person implements Comparable<Person>{
    private String name;
    private int age;


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

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

    public Person() {
    }

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

    @Override
    public int compareTo(Person o) {
        if (this.age > o.age){
            return 1;
        }else if (this.age < o.age){
            return -1;
        }else {
            return 0;
        }
    }
}

import java.util.Set;
import java.util.TreeSet;

public class TreeSetPersonDemo01 {

    public static void main(String[] args){
        Set<Person> all = new TreeSet<Person>();
        all.add(new Person("张三",10));
        all.add(new Person("李四",10));
        all.add(new Person("王五", 11));
        all.add(new Person("赵六", 12));
        all.add(new Person("孙七", 13));
        System.out.println(all);
    }
}
//[Person{name='张三', age=10}, Person{name='王五', age=11}, Person{name='赵六', age=12}, Person{name='孙七', age=13}]
2.4.4、关于重复元素的说明(重点)

之前使用 Comparable 完成的对于重复元素的判断,那么 Set 接口定义的时候本身就是不允许重复元素的,那么证明 如果现在真的是有重复元素的话,使用 HashSet 也同样可以进行区分。

import java.util.HashSet;
import java.util.Iterator;

public class Demo6 {
    //HashSet:散列存放(哈希表在学习HashMap集合时讲解)
    public static void main(String[] args){
        HashSet<String> set = new HashSet<>();
        set.add("1");
        set.add("2");
        set.add("3");
        set.add("4");
        Boolean f = set.add("1");
        System.out.println(f);
       
    }
}
//f = false
总结

关于 TreeSet 的排序实现,如果是集合中对象是自定义的或者说其他系统定义的类没有实现 Comparable 接口,则不能实现 TreeSet 的排序,会报类型转换(转向 Comparable 接口)错误。 换句话说要添加到 TreeSet 集合中的对象的类型必须实现了 Comparable 接口。

不过 TreeSet 的集合因为借用了 Comparable 接口,同时可以去除重复值,而 HashSet 虽然是 Set 接口子类,但是对于没有复写 Object 的 equals 和 hashCode 方法的对象,加入了 HashSet 集合中也是不能去掉重复值的。

2.4.5、Set类方法
2.4.5.1、add/addAll
boolean add​(E e)
如果指定的元素尚不存在,则将其添加到此集合(可选操作)。 更正式地说,如果集合中不包含元素e2 , Objects.equals(e, e2)指定的元素e添加到此集合中,如Objects.equals(e, e2) 。 如果此set已包含该元素,则调用将保持set不变并返回false 。 结合对构造函数的限制,这可以确保集合永远不会包含重复元素。 
上述规定并不意味着集合必须接受所有要素; sets可以拒绝添加任何特定元素,包括null ,并抛出异常,如Collection.add的规范中所述 。 单个集合实现应清楚地记录对它们可能包含的元素的任何限制。 

Specified by: 
add接口 Collection<E> 
参数 
e - 要添加到此集合的元素 
结果 
true如果此集合尚未包含指定的元素 
异常 
UnsupportedOperationException - 如果此集合不支持 add操作 
ClassCastException - 如果指定元素的类阻止将其添加到此集合中 
NullPointerException - 如果指定的元素为null且此set不允许null元素 
IllegalArgumentException - 如果指定元素的某些属性阻止将其添加到此集合中 


3、集合输出(重点)

已经学习过了基本的集合操作,那么对于集合的输出本身也是有多种形式的,可以使用如下的几种方式:

· Iterator 迭代输出(90%)、ListIterator(5%)、Enumeration(1%)、foreach(4%)

只要是碰到了集合,则输出的时候想都不想就使用 Iterator 进行输出。”

3.1、Iterator(绝对重点)

Iterator 属于迭代输出,基本的操作原理:是不断的判断是否有下一个元素,有的话,则直接输出。

此接口定义如下:

public interface Iterator<E>

要想使用此接口,则必须使用 Collection 接口,在 Collection 接口中规定了一个 iterator()方法,可以用于为 Iterator 接口进行实例化操作。

此接口规定了以下的三个方法:
在这里插入图片描述
通过 Collection 接口为其进行实例化之后,一定要记住,Iterator 中的操作指针是在第一条元素之上,当调用 next()方 法的时候,获取当前指针指向的值并向下移动,使用 hasNext()可以检查序列中是否还有元素。
在这里插入图片描述

import java.util.HashSet;
import java.util.Iterator;

public class Demo6 {
    //HashSet:散列存放(哈希表在学习HashMap集合时讲解)
    public static void main(String[] args){
        HashSet<String> set = new HashSet<>();
        set.add("1");
        set.add("2");
        set.add("3");
        set.add("4");
        Iterator<String> iterator = set.iterator();
        //判断是否有下一个元素
        while (iterator.hasNext()){
        	//取出当前元素
            System.out.println(iterator.next());
        }
    }
}

以上的操作是 Iterator 接口使用最多的形式,也是一个标准的输出形式。

但是在使用 Iterator 输出的时候有一点必须注意,在进行迭代输出的时候如果要想删除当前元素,则只能使用 Iterator 接口中的 remove()方法,而不能使用集合中的 remove()方法。否则将出现未知的错误。

import java.util.*;

public class Demo9 {
    public static void main(String[] args) {
        Collection<String> all = new ArrayList<String>();
        all.add("A");
        all.add("B");
        all.add("C");
        all.add("D");
        all.add("E");
        Iterator<String> iter = all.iterator();
        while (iter.hasNext()){
            String str = iter.next();
            if (str.equals("C")){
                //错误的,调用了集合中的删除
                iter.remove();
            }else {
                System.out.println(str + " ");
            }
        }
    }

}

在这里插入图片描述

此时出现了错误,因为原本的要输出的集合的内容被破坏掉了

import java.util.*;

public class Demo9 {
    public static void main(String[] args) {
        Collection<String> all = new ArrayList<String>();
        all.add("A");
        all.add("B");
        all.add("C");
        all.add("D");
        all.add("E");
        Iterator<String> iter = all.iterator();
        while (iter.hasNext()){
            String str = iter.next();
            if (str.equals("C")){
                //错误的,调用了集合中的删除
                iter.remove();
            }else {
                System.out.println(str + " ");
            }
        }
    }

}

结果:A 
	B 
	D 
	E

但是,从实际的开发角度看,元素的删除操作出现的几率是很小的,基本上可以忽略,即:集合中很少有删除元素 的操作。

Iterator 接口本身可以完成输出的功能,但是此接口只能进行由前向后的单向输出。如果要想进行双向输出,则必须 使用其子接口 —— ListIterator。

import java.util.List;
import java.util.Map;
import java.util.Set;

public class Demo10 {
    public static void main(String[] args) {
        List<String> list = List.of("锄禾日当午","汗滴禾下土");
        for (String s:list){
            System.out.println(s);
        }
        Set<String> set = Set.of("锄禾日当午","汗滴禾下土");
        for (String s:set){
            System.out.println(s);
        }

        Map<String,String> haha1 = Map.of("haha","1");
    }
}

4、Map 接口(重点)

以上的 Collection 中,每次操作的都是一个对象,如果现在假设要操作一对对象,则就必须使用 Map 了,类似于以 下一种情况:

//map:键不能重复
张三 123456 
李四 234567

那么保存以上信息的时候使用 Collection 就不那么方便,所以要使用 Map 接口。里面的所有内容都按照 key-value 的形式保存,也称为二元偶对象。

public interface Map<K,V>

此接口与 Collection 接口没有任何的关系,是第二大的集合操作接口。此接口常用方法如下:

在这里插入图片描述

Map 本身是一个接口,所以一般会使用以下的几个子类:HashMap、TreeMap、Hashtable

4.1、哈希表

视图

在这里插入图片描述

如上图:
初始桶数量:16
散列因子:0.75,当桶存储了百分之七十五时,扩容,16-->32
以取余条件为例:17和33余数都为一,存储在一个地方,如上图以形式数组
存储,当哈希桶中的数据量大于8时,从链表转换为红黑二叉树
当哈希桶中的数据减少到6时,从红黑二叉树转换为链表
4.2、新的子类:HashMap(重点)

HashMap 是 Map 的子类,此类的定义如下:

public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable

此类继承了 AbstractMap 类,同时可以被克隆,可以被序列化下来。

范例:向集合中增加内容

import java.util.HashMap;
import java.util.Map;

public class HashMapDemo01 {

    public static void main(String[] args){
        Map<Integer,String> map = new HashMap<Integer, String>();
        map.put(1,"张三A");
        map.put(1,"张三B");
        map.put(2,"李四");
        map.put(3,"王五");
        System.out.println(map.get(1));
    }
}
//1,张三B

Code:

import java.util.HashMap;
import java.util.Set;

public class Demo8 {

    public static void main(String[] args){
        HashMap<String,String> data = new HashMap<>();
        data.put("key1","1");
        data.put("key2","2");
        String value = data.get("key1");
        System.out.println(value);

        Set<String> set = data.keySet();
        for (String key:set){
            System.out.println(key+"->"+data.get(key));
        }
    }
}
4.3、旧的子类:Hashtable(重点)

Hashtable 是一个最早的 keyvalue 的操作类,本身是在 JDK 1.0 的时候推出的。其基本操作与 HashMap 是类似的。

import java.util.Collection;
import java.util.Hashtable;
import java.util.Map;

public class HashtableDemo01 {
    public static void main(String[] args){
        Map<String,Integer> numbers = new Hashtable<String,Integer>();
        numbers.put("one",1);
        numbers.put("two",2);
        numbers.put("three",3);
        Integer n = numbers.get("two");
        if (n != null) {
            System.out.println("two = " + n);
        }
    }
}

操作的时候,可以发现与 HashMap 基本上没有什么区别,而且本身都是以 Map 为操作标准的,所以操作的结果形式 都一样。但是 Hashtable 中是不能向集合中插入 null 值的。

4.4、HashMap 与 Hashtable 的区别(重点)

在整个集合中除了 ArrayList 和 Vector 的区别之外,另外一个最重要的区别就是 HashMap 与 Hashtable 的区别。

在这里插入图片描述

HashMap 与 Hashtable和 ConcurrenHashMap的区别

在这里插入图片描述

4.5、排序的子类:TreeMap(理解)

TreeMap 子类是允许 key 进行排序的操作子类,其本身在操作的时候将按照 key 进行排序,另外,key 中的内容可以 为任意的对象,但是要求对象所在的类必须实现 Comparable 接口。

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo01 {
public static void main(String[] args) {
Map<String, String> map = new TreeMap<String, String>();
map.put("ZS", "张三");
map.put("LS", "李四");
map.put("WW", "王五");
map.put("ZL", "赵六");
map.put("SQ", "孙七");
Set<String> set = map.keySet(); // 得到全部的key
Iterator<String> iter = set.iterator();
while (iter.hasNext()) {
String i = iter.next(); // 得到key
System.out.println(i + " --:> " + map.get(i));
}
}
}

此时的结果已经排序成功了,但是从一般的开发角度来看,在使用 Map 接口的时候并不关心其是否排序,所以此类 只需要知道其特点即可。

4.6、关于 Map 集合的输出
在 Collection 接口中,可以使用 iterator()方法为 Iterator 接口实例化,并进行输出操作,但是在 Map 接口中并没有此方法的定义,所以 Map 接口本身是不能直接使用 Iterator 进行输出的。
因为 Map 接口中存放的每一个内容都是一对值,而使用 Iterator 接口输出的时候,每次取出的都实际上是一个完整的对象。如果此时非要使用 Iterator 进行输出的话,则可以按照如下的步骤进行:

1、 使用 Map 接口中的 entrySet()方法将 Map 接口的全部内容变为 Set 集合

2、 可以使用 Set 接口中定义的 iterator()方法为 Iterator 接口进行实例化

3、 之后使用 Iterator 接口进行迭代输出,每一次的迭代都可以取得一个 Map.Entry 的实例

4、 通过 Map.Entry 进行 key 和 value 的分离
那么,到底什么是 Map.Entry 呢?

Map.Entry 本身是一个接口。此接口是定义在 Map 接口内部的,是 Map 的内部接口。此内部接口使用 static 进行定义,
所以此接口将成为外部接口。

实际上来讲,对于每一个存放到 Map 集合中的 key 和 value 都是将其变为了 Map.Entry 并且将 Map.Entry 保存在了Map 

在这里插入图片描述

在 Map.Entry 接口中以下的方法最为常用:

在这里插入图片描述

package org.listdemo.mapoutdemo;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapOutDemo01 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("ZS", "张三");
map.put("LS", "李四");
map.put("WW", "王五");
map.put("ZL", "赵六");
map.put("SQ", "孙七");
Set<Map.Entry<String, String>> set = map.entrySet();// 变为Set实例
Iterator<Map.Entry<String, String>> iter = set.iterator();
while (iter.hasNext()) {
Map.Entry<String, String> me = iter.next();
System.out.println(me.getKey() + " --> " + me.getValue());
}
}
}
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

public class Demo8 {

    public static void main(String[] args){
        HashMap<String,String> data = new HashMap<>();
        data.put("key1","1");
        data.put("key2","2");
        String value = data.get("key1");
        System.out.println(value);

        Set<String> set = data.keySet();
        for (String key:set){
            System.out.println(key+"->"+data.get(key));
        }
        Collection<String> values = data.values();
        for (String v:values){
            System.out.println(v);
        }
    }
}

import java.util.List;
import java.util.Map;
import java.util.Set;

public class Demo10 {
    public static void main(String[] args) {
        List<String> list = List.of("锄禾日当午","汗滴禾下土");
        for (String s:list){
            System.out.println(s);
        }
        Set<String> set = Set.of("锄禾日当午","汗滴禾下土");
        for (String s:set){
            System.out.println(s);
        }

        Map<String,String> haha1 = Map.of("haha","1");
    }
}

4.7、Map方法

1、size
int size()
返回此映射中键 - 值映射的数量。 如果地图包含超过Integer.MAX_VALUE元素,则返回Integer.MAX_VALUE 。 
结果 
此映射中键 - 值映射的数量 

2、isEmpty
boolean isEmpty()
如果此映射不包含键 - 值映射,则返回 true 。 
结果 
true如果此映射不包含键 - 值映射 
3、containsKey
boolean containsKey​(Object key)
如果此映射包含指定键的映射,则返回true 。 更正式地,当且仅当此映射包含键k的映射(例如true时,才返回Objects.equals(key, k) 。 (最多可以有一个这样的映射。) 
参数 
key - 要测试其在此地图中的存在的密钥 
结果 
true如果此映射包含指定键的映射 
异常 
ClassCastException - 如果该地区的密码是不适合的某种类型( optional ) 
NullPointerException - 如果指定的键为空且此映射不允许空键( optional ) 
4、containValue
boolean containsValue​(Object value)
如果此映射将一个或多个键映射到指定值,则返回true 。 更正式地,返回true当且仅当此映射包含的至少一个映射到一个值v使得Objects.equals(value, v) 。 对于Map接口的大多数实现,此操作可能需要在映射大小中线性时间。 
参数 
value - 要测试其在此映射中的存在的值 
结果 
true如果此映射将一个或多个键映射到指定的值 
异常 
ClassCastException - 如果该地图的数据类型不正确( optional ) 
NullPointerException - 如果指定的值为null并且此映射不允许空值( optional ) 

5、get
get​(Object key)
返回指定键映射到的值,如果此映射不包含键的映射,则返回null 。 
更正式地说,如果此映射包含从键k到值v的映射,使得Objects.equals(key, k) ,则此方法返回v ; 否则返回null 。 (最多可以有一个这样的映射。) 

如果此映射允许空值,则返回值null 不一定表示映射不包含该键的映射; 地图也可能将密钥明确映射到null 。 可以使用containsKey操作来区分这两种情况。 

参数 
key - 要返回其关联值的键 
结果 
指定键映射到的值,如果此映射不包含键的映射, null 
异常 
ClassCastException - 如果该地区的密码是不适合的某种类型( optional ) 
NullPointerException - 如果指定的键为空且此映射不允许空键( optional ) 

6、put
put​(K key, V value)
将指定的值与此映射中的指定键相关联(可选操作)。 如果映射先前包含键的映射,则旧值将替换为指定的值。 (当且仅当m.containsKey(k)将返回true地图m才会包含密钥k的映射。) 
参数 
key - 与指定值关联的键 
value - 与指定键关联的值 
结果 
与key关联的先前值,如果null没有映射, key 。 (A null返回也可以指示先前与null关联的地图与key ,如果实现支持null值。) 
异常 
UnsupportedOperationException - 如果此地图不支持 put 
ClassCastException - 如果指定键或值的类阻止它存储在此映射中 
NullPointerException - 如果指定的键或值为null,并且此映射不允许空键或值 
IllegalArgumentException - 如果指定键或值的某些属性阻止它存储在此映射中 

7、remove
remove​(Object key)
如果存在,则从该映射中移除键的映射(可选操作)。 更正式地说,如果此映射包含从键k到值v的映射,例如Objects.equals(key, k) ,则删除该映射。 (地图最多可以包含一个这样的映射。) 
返回此映射先前与该键关联的值,如果映射不包含该键的映射,则返回null 。 

如果此映射允许空值,则返回值null 不一定表示映射不包含键的映射; 地图也可能明确地将密钥映射到null 。 

一旦调用返回,映射将不包含指定键的映射。 

参数 
key - 要从地图中删除其映射的键 
结果 
与 key关联的先前值,如果 null没有映射, key 。 
异常 
UnsupportedOperationException - 如果此地图不支持 remove操作 
ClassCastException - 如果该地区的密码是不适合的某种类型( optional ) 
NullPointerException - 如果指定的键为空且此映射不允许空键( optional )
8、putAll
void putAll​(Map<? extends K,​? extends V> m)
将指定映射中的所有映射复制到此映射(可选操作)。 对于从指定映射中的键k到值v每个映射,此调用的效果等效于在此映射上调用put(k, v)的效果。 如果在操作过程中修改了指定的映射,则此操作的行为是不确定的。 
参数 
m - 要存储在此映射中的映射 
异常 
UnsupportedOperationException - 如果此地图不支持 putAll操作 
ClassCastException - 如果指定映射中的键或值的类阻止它存储在此映射中 
NullPointerException - 如果指定的映射为null,或者此映射不允许空键或值,并且指定的映射包含空键或值 
IllegalArgumentException - 如果指定映射中的键或值的某些属性阻止将其存储在此映射中 

9、clear
void clear()
从此映射中删除所有映射(可选操作)。 此调用返回后,映射将为空。 
异常 
UnsupportedOperationException - 如果此地图不支持 clear操作 
10、equals
boolean equals​(Object o)
将指定对象与此映射进行比较以获得相等性。 如果给定对象也是一个映射,并且两个映射表示相同的映射,则返回true 。 更正式地说,如果m1.entrySet().equals(m2.entrySet()) ,则两个映射m1和m2表示相同的映射。 这可确保equals方法在Map接口的不同实现中正常工作。 
重写: 
equals在类 Object 
参数 
o - 要与此映射进行相等性比较的对象 
结果 
true如果指定的对象等于此映射 
另请参见: 
Object.hashCode() , HashMap 

11、replace/replaceAll
default boolean replace​(K key, V oldValue, V newValue)
仅当前映射到指定值时,才替换指定键的条目。 
实现要求: 
对于此map ,默认实现等效于: 
   if (map.containsKey(key) && Objects.equals(map.get(key), value)) { map.put(key, newValue); return true; } else return false;  如果oldValue为null,则默认实现不会为不支持空值的映射抛出NullPointerException,除非newValue也为null。 
默认实现不保证此方法的同步或原子性属性。 提供原子性保证的任何实现都必须覆盖此方法并记录其并发属性。 

参数 
key - 与指定值关联的键 
oldValue - 期望与指定密钥关联的值 
newValue - 要与指定键关联的值 
结果 
true如果值已被替换 
异常 
UnsupportedOperationException -如果 put操作不受此地图支持( optional ) 
ClassCastException - 如果指定键或值的类阻止它存储在此映射中 
NullPointerException - 如果指定的键或newValue为null,并且此映射不允许null键或值 
NullPointerException - 如果oldValue为null且此映射不允许空值( optional ) 
IllegalArgumentException - 如果指定键或值的某些属性阻止它存储在此映射中 

5、Collections 类(理解)

Collections 实际上是一个集合的操作类,此类的定义如下:

这个类与 Collection 接口没有任何的关系。是一个单独存在的类。

第四节:IO

1、File类

1.1、字符
1、srparatorChar
public static final char separatorChar
系统相关的默认名称分隔符。 此字段初始化为包含系统属性file.separator的第一个字符。
在UNIX系统上,此字段的值为'/' ; 在Microsoft Windows系统上,它是'\\' 。
2、separator
public static final String separator系统相关的默认名称分隔符,为方便起见,表示为字符串。 
该字符串包含单个字符,即separatorChar 。 
3、pathSeparatorChar
public static final char pathSeparatorChar与系统相关的路径分隔符。 
此字段初始化为包含系统属性值path.separator的第一个字符。 
此字符用于分隔作为路径列表给出的文件序列中的文件名。 在UNIX系统上,此字符为':' ; 在Microsoft Windows系统上,它是';' 。 
4、pathSeparator
public static final String pathSeparator与系统相关的路径分隔符,为方便起见,表示为字符串。 
该字符串包含单个字符,即pathSeparatorChar 。 

文件和目录路径名的抽象表示。 
字段

在这里插入图片描述

example:
//路径分割符:跨平台
        System.out.println(File.pathSeparator);
        //名称分割符
        System.out.println(File.separator);
        
        结果:;		\
1.2、构造方法:前三个常用

在这里插入图片描述

1、File
public File​(String pathname)通过将给定的路径名字符串转换为抽象路径名来创建新的File实例。 如果给定的字符串是空字符串,则结果是空的抽象路径名。 
参数 
pathname - 路径名字符串 
异常 
NullPointerException - 如果 pathname参数为 null 

 File dir = new File("D://1.txt");
2、File
从父路径名字符串和子路径名字符串创建新的File实例。 
如果parent是null则创建新的File实例,就好像通过在给定的child路径名字符串上调用单参数File构造函数child 。 

否则, parent路径名字符串用于表示目录, child路径名字符串用于表示目录或文件。 如果child路径名字符串是绝对的,那么它将以系统相关的方式转换为相对路径名。 如果parent是空字符串,则通过将child转换为抽象路径名并根据系统相关的默认目录解析结果来创建新的File实例。 否则,将每个路径名字符串转换为抽象路径名,并针对父路径解析子抽象路径名。 

参数 
parent - 父路径名字符串 
child - 子路径名字符串 
异常 
NullPointerException - 如果 child是 null 
File a = new File(dir,"a.txt");
1.3、方法

实例操作在此环境下演示

public class Demo1 {

    public static void main(String[] args) throws IOException {
        File dir = new File("D://1.txt");
        //dir.createNewFile();//创建文档
        //创建目录
        //dir.mkdir();
        File a = new File(dir,"a.txt");
        //a.createNewFile();

        File b = new File("D:\\haha,b.txt");
        //b.createNewFile();
        //a.delete();
        //b.delete();

        //路径分割符:跨平台
        //System.out.println(File.pathSeparator);
        //名称分割符
        //System.out.println(File.separator);
        System.out.println(a.getPath());
    }
}
1、getAbsolueFile/getAbsoluePath

在这里插入图片描述

public File getAbsoluteFile()
返回此抽象路径名的绝对形式。 相当于new File(this.getAbsolutePath()) 。 
结果 
绝对抽象路径名,表示与此抽象路径名相同的文件或目录 
异常 
SecurityException - 如果无法访问所需的系统属性值。 

例子:
File dir = new File("D://1.txt");
File a = new File(dir,"a.txt");
System.out.println(a.getAbsoluteFile());
返回路径
//D:\1.txt\a.txt
public String getAbsolutePath()
返回此抽象路径名的绝对路径名字符串。 
如果此抽象路径名已经是绝对路径名,则只需返回路径名字符串,就好像通过getPath()方法一样。 如果此抽象路径名是空抽象路径名,则返回当前用户目录的路径名字符串,该字符串由系统属性user.dir命名。 否则,此路径名将以与系统相关的方式解析。 在UNIX系统上,通过将相对路径名解析为当前用户目录,使其成为绝对路径名。 在Microsoft Windows系统上,通过将路径名解析为路径名所指定的驱动器的当前目录(如果有),使相对路径名成为绝对路径名。 如果没有,则针对当前用户目录解析。 

结果 
绝对路径名字符串,表示与此抽象路径名相同的文件或目录 
异常 
SecurityException - 如果无法访问所需的系统属性值。 
例子:
File dir = new File("D://1.txt");
File a = new File(dir,"a.txt");
System.out.println(a.getAbsoluteFile());
返回路径
//D:\1.txt\a.txt
2、getName
返回此抽象路径名表示的文件或目录的名称。 这只是路径名称序列中的姓氏。 如果路径名的名称序列为空,则返回空字符串。 
结果 
此抽象路径名表示的文件或目录的名称,如果此路径名的名称序列为空,则为空字符串 
例子:
File dir = new File("D://1.txt");
File a = new File(dir,"a.txt");
System.out.println(a.getName());
返回名称
a.txt
3、getParent/getParentFile
public String getParent()
返回此抽象路径名父项的路径名字符串,如果此路径名未指定父目录,则返回null 。 
抽象路径名的父节点包含路径名的前缀(如果有),以及路径名的名称序列中的每个名称(除了最后一个)。 如果名称序列为空,则路径名不会命名父目录。 

结果 
此抽象路径名指定的父目录的路径名字符串,如果此路径名未指定父路径, null 
File dir = new File("D://1.txt");
File a = new File(dir,"a.txt");
System.out.println(a.getParent());
结果
dir
public File getParentFile()
返回此抽象路径名父项的抽象路径名,如果此路径名未指定父目录,则返回null 。 
抽象路径名的父节点包含路径名的前缀(如果有),以及路径名的名称序列中的每个名称(除了最后一个)。 如果名称序列为空,则路径名不会命名父目录。 

结果 
此抽象路径名指定的父目录的抽象路径名,如果此路径名未指定父路径, null 

File dir = new File("D://1.txt");
File a = new File(dir,"a.txt");
System.out.println(a.getParent());
结果
D:\1.txt
4、getPath
public String getPath()
将此抽象路径名转换为路径名字符串。 生成的字符串使用default name-separator character分隔名称序列中的名称。 
结果 
此抽象路径名的字符串形式 
System.out.println(a.getPath());

结果
D:\1.txt\a.txt
5、length
public long length()
返回此抽象路径名表示的文件的长度。 如果此路径名表示目录,则返回值未指定。 
如果需要区分I / O异常与返回0L的情况,或者同时需要同一文件的多个属性,则可以使用Files.readAttributes方法。 

结果 
此抽象路径名表示的文件的长度(以字节为单位),如果该文件不存在, 0L 。 对于表示系统相关实体(如设备或管道)的路径名,某些操作系统可能会返回0L 。 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkRead(java.lang.String)方法拒绝对文件的读访问权 
System.out.println(a.length());
6、exists
public boolean exists()
测试此抽象路径名表示的文件或目录是否存在。 
结果 
true当且仅当此抽象路径名表示的文件或目录存在时; 否则为false 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkRead(java.lang.String)方法拒绝对文件或目录的读访问权 

System.out.println(a.exists());
//true
7、list
public String[] list​(FilenameFilter filter)
返回一个字符串数组,用于命名由此抽象路径名表示的目录中的文件和目录,以满足指定的过滤器。 此方法的行为与list()方法的行为相同,只是返回的数组中的字符串必须满足过滤器。 如果给定的filter是null则接受所有名称。 否则,当且仅当在此抽象路径名上调用过滤器的FilenameFilter.accept(File, String)方法以及其表示的目录中的文件或目录的名称时,才会生成值true的名称。 
参数 
filter - 文件名过滤器 
结果 
一个字符串数组,用于命名由此抽象路径名表示的目录中的文件和目录,这些文件和目录由给定的filter接受。 如果目录为空或过滤器未接受任何名称,则该数组将为空。 如果此抽象路径名不表示目录,或者发生I / O错误,则返回null 。 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkRead(String)方法拒绝对目录的读访问权
8、ListFiles
public File[] listFiles()
返回一个抽象路径名数组,表示此抽象路径名表示的目录中的文件。 
如果此抽象路径名不表示目录,则此方法返回null 。 否则返回File对象的数组,每个文件或目录对应一个对象。 表示目录本身的路径名和目录的父目录不包含在结果中。 每个生成的抽象路径名都是使用File(File, String)构造函数从此抽象路径名构造的。 因此,如果此路径名是绝对的,那么每个结果路径名都是绝对的; 如果此路径名是相对的,则每个结果路径名将相对于同一目录。 

无法保证结果数组中的名称字符串将以任何特定顺序出现; 特别是,它们不能保证按字母顺序出现。 

请注意, Files类定义了newDirectoryStream方法来打开目录并迭代目录中文件的名称。 使用非常大的目录时,这可能会占用更少的资源。 

结果 
一组抽象路径名,表示此抽象路径名表示的目录中的文件和目录。 如果目录为空,则数组将为空。 如果此抽象路径名不表示目录,或者发生I / O错误,则返回null 。 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkRead(String)方法拒绝对目录的读访问权限 

9、renameTo
public boolean renameTo​(File dest)
重命名此抽象路径名表示的文件。 
此方法行为的许多方面本质上都依赖于平台:重命名操作可能无法将文件从一个文件系统移动到另一个文件系统,它可能不是原子的,如果具有目标抽象路径名的文件,它可能不会成功已经存在。 应始终检查返回值以确保重命名操作成功。 

请注意, Files类定义了move方法,以独立于平台的方式移动或重命名文件。 

参数 
dest - 指定文件的新抽象路径名 
结果 
true当且仅当重命名成功时; 否则为false 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkWrite(java.lang.String)方法拒绝对旧路径名或新路径名的写访问权 
NullPointerException - 如果参数 dest是 null 

在这里插入图片描述

10、isAbsolute
测试此抽象路径名是否为绝对路径。 绝对路径名的定义取决于系统。 在UNIX系统上,如果路径名的前缀为"/" ,则路径名是绝对路径。 在Microsoft Windows系统上,如果路径名的前缀是驱动器说明符后跟"\\" ,或者前缀为"\\\\" ,则路径名是绝对路径名。 
结果 
true如果此抽象路径名是绝对路径, false 
System.out.println(a.isAbsolute());
结果
true
11、getCanonicalPath
public String getCanonicalPath() throws IOException
返回此抽象路径名的规范路径名字符串。 
规范路径名既是绝对的,也是唯一的。 规范形式的精确定义取决于系统。 如果需要,此方法首先将此路径名转换为绝对形式,就像调用getAbsolutePath()方法一样,然后以系统相关的方式将其映射到其唯一形式。 这通常涉及从路径名中删除冗余名称(如"."和".." ,解析符号链接(在UNIX平台上),以及将驱动器号转换为标准大小写(在Microsoft Windows平台上)。 

表示现有文件或目录的每个路径名都具有唯一的规范形式。 表示不存在的文件或目录的每个路径名也具有唯一的规范形式。 在创建文件或目录之后,不存在的文件或目录的路径名的规范形式可能与相同路径名的规范形式不同。 类似地,在删除文件或目录之后,现有文件或目录的路径名的规范形式可以与相同路径名的规范形式不同。 

结果 
规范路径名字符串,表示与此抽象路径名相同的文件或目录 
异常 
IOException - 如果发生I / O错误,这是可能的,因为规范路径名的构造可能需要文件系统查询 
SecurityException - 如果无法访问所需的系统属性值,或者存在安全管理器且其 SecurityManager.checkRead(java.io.FileDescriptor)方法拒绝对文件的读访问权限 
System.out.println(a.getCanonicalPath());
D:\1.txt\a.txt
12、getCanonicalFile
public File getCanonicalFile() throws IOException
返回此抽象路径名的规范形式。 相当于new File(this.getCanonicalPath()) 。 
结果 
规范路径名字符串,表示与此抽象路径名相同的文件或目录 
异常 
IOException - 如果发生I / O错误,这是可能的,因为规范路径名的构造可能需要文件系统查询 
SecurityException - 如果无法访问所需的系统属性值,或者存在安全管理器且其 SecurityManager.checkRead(java.io.FileDescriptor)方法拒绝对文件的读访问权限 
System.out.println(a.getCanonicalFile());
D:\1.txt\a.txt
13、canRead/canWrite
public boolean canRead()
测试应用程序是否可以读取此抽象路径名表示的文件。 在某些平台上,可以启动具有特殊权限的Java虚拟机,以允许它读取标记为不可读的文件。 因此,即使该文件没有读取权限,此方法也可能返回true 。 
结果 
true当且仅当此抽象路径名指定的文件存在且可由应用程序读取时; 否则为false 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkRead(java.lang.String)方法拒绝对该文件的读访问权 

public boolean canWrite()
测试应用程序是否可以修改此抽象路径名表示的文件。 在某些平台上,可以使用特殊权限启动Java虚拟机,以允许它修改标记为只读的文件。 因此,即使文件标记为只读,此方法也可能返回true 。 
结果 
true当且仅当文件系统实际包含由此抽象路径名表示的文件且允许应用程序写入文件时; 否则为false 。 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkWrite(java.lang.String)方法拒绝对文件的写访问权 

14、isDirectory/isFile/isHidden
public boolean isDirectory()
测试此抽象路径名表示的文件是否为目录。 
如果需要区分I / O异常与文件不是目录的情况,或者同时需要同一文件的多个属性的情况,则可以使用Files.readAttributes方法。 

结果 
true当且仅当此抽象路径名表示的文件存在并且是目录时; 否则为false 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkRead(java.lang.String)方法拒绝对文件的读访问权 
public boolean isFile()
测试此抽象路径名表示的文件是否为普通文件。 如果文件不是目录,则该文件是正常的 ,此外,它还满足其他系统相关标准。 由Java应用程序创建的任何非目录文件都保证是普通文件。 
如果需要区分I / O异常与文件不是普通文件的情况,或者同时需要同一文件的多个属性的情况,则可以使用Files.readAttributes方法。 

结果 
true当且仅当此抽象路径名表示的文件存在并且是普通文件时; 否则为false 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkRead(java.lang.String)方法拒绝对文件的读访问权 
public boolean isHidden()
测试此抽象路径名指定的文件是否为隐藏文件。 隐藏的确切定义取决于系统。 在UNIX系统上,如果文件的名称以句点字符( '.' )开头,则认为该文件是隐藏的。 在Microsoft Windows系统上,如果文件在文件系统中已标记为文件,则认为该文件是隐藏的。 
结果 
true当且仅当根据底层平台的约定隐藏此抽象路径名表示的文件时 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkRead(java.lang.String)方法拒绝对文件的读访问权 
15、createNewFile
public boolean createNewFile() throws IOException
当且仅当具有此名称的文件尚不存在时,以原子方式创建由此抽象路径名命名的新空文件。 检查文件是否存在以及文件的创建(如果不存在)是针对可能影响文件的所有其他文件系统活动的原子操作。 
注意:此方法不应用于文件锁定,因为无法使生成的协议可靠地工作。 应该使用FileLock设施。 

结果 
true如果指定的文件不存在且已成功创建; false如果指定的文件已存在 
异常 
IOException - 如果发生I / O错误 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkWrite(java.lang.String)方法拒绝对文件的写访问权限 
File dir = new File("D://1.txt");
dir.createNewFile();//创建文档
16、delete
public boolean delete()
删除此抽象路径名表示的文件或目录。 如果此路径名表示目录,则该目录必须为空才能被删除。 
请注意, Files类定义delete方法, 以便在无法删除文件时抛出IOException 。 这对于错误报告和诊断无法删除文件的原因很有用。 

结果 
true当且仅当文件或目录被成功删除时; 否则为false 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkDelete(java.lang.String)方法拒绝对文件的删除访问权限 

File a = new File(dir,"a.txt");
a.delete();
17、mkdir
创建此抽象路径名指定的目录。 
结果 
true当且仅当目录已创建时; 否则为false 
异常 
SecurityException - 如果存在安全管理器且其 SecurityManager.checkWrite(java.lang.String)方法不允许创建指定目录 

File dir = new File("D://1.txt");
dir.mkdir();
1.4、文件遍历

length,getName、endWith。listFile实际使用

package com.demo1;

import java.io.File;

public class Demo2 {

    //java.io.*
    public static void main(String[] args) {
        File e = new File("D:\\视频课程");
        File[] files = e.listFiles();
        listFiles(files);
    }

    private static void listFiles(File[] files) {
        if (files != null && files.length > 0){
            for (File file:files){
                if (file.isFile()){
                    //endWith文件后缀
                    if (file.getName().endsWith(".mp4")){
                        //找到了mp4文件
                        if (file.length() > 100 * 1024 * 1024) {
                            //大于100m的文件=100字节*1024=100kb*1024=100Mb
                            System.out.println("找到了一个 " + file.length() + " Mp4文件");
                        }
                    }
                }else{
                    //文件夹
                    File[] files2 = file.listFiles();
                    listFiles(files2);
                }

            }
        }
    }
}

1.5、文件过滤器(了解)
1.6、相对路径和绝对路径
相对路径:从盘符开始,是一个完整的路径,例如:c://a.txt
相对路径:在Java代码中是相对于项目目录路径,这是一个不完整的便捷路径
在java开发中很常用例如:a.txt

2、流:

import java.io.*;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;


/**
 * @author liweijie
 */
public class Demo {
    /**
     * IO流概述
     *  可以将这种数据传输操作,看做一种数据的流动 , 按照流动的方向分为输入Input和输出Output
     *  Java中的IO操作主要指的是 java.io包下的一些常用类的使用. 通过这些常用类对数据进行读取(输入Input) 和 写出(输出Output)
     *
     * IO流的分类:
     *  按照流的方向来分,可以分为:输入流和输出流.
     *  按照流动的数据类型来分,可以分为:字节流和字符流
     *
     *     字节流:
     *          -   输入流 :   InputStream
     *          -   输出流 :   OutputStream
     *     字符流:
     *          -   输入流 :   Reader
     *          -   输出流 :   Writer
     *
     *
     * 一切皆字节:
     *      计算机中的任何数据(文本,图片,视频,音乐等等)都是以二进制的形式存储的.
     *      在数据传输时 也都是以二进制的形式存储的.
     *      后续学习的任何流 , 在传输时底层都是二进制.
     * @param args
     */
    public static void main(String[] args) throws FileNotFoundException {


    }

}
2.1、OutputStream
2.1.1、方法
2.1.1.1、close()
public void close() throws IOException
关闭此输出流并释放与此流关联的所有系统资源。 close的一般合同是它关闭输出流。 封闭流无法执行输出操作,无法重新打开。 
该close的方法OutputStream什么都不做。 

Specified by: 
close ,界面 AutoCloseable 
Specified by: 
close ,界面 Closeable 
异常 
IOException - 如果发生I / O错误。 
2.1.1.2、flush
public void flush() throws IOException
刷新此输出流并强制写出任何缓冲的输出字节。 flush的一般合同是调用它表示,如果先前写入的任何字节已被输出流的实现缓冲,则应立即将这些字节写入其预期目的地。 
如果该流的预期目的地是由底层操作系统提供的抽象,例如文件,则刷新流仅保证先前写入流的字节被传递到操作系统以进行写入; 它不能保证它们实际上写入物理设备,如磁盘驱动器。 

flush方法OutputStream什么也没做。 

Specified by: 
flush在界面 Flushable 
异常 
IOException - 如果发生I / O错误。 

2.1.1.3、write
public void write​(byte[] b, int off, int len) throws IOException
将从偏移量off开始的指定字节数组中的len字节写入此输出流。 write(b, off, len)的一般合同是数组b中的一些字节按b写入输出流; element b[off]是写入的第一个字节, b[off+len-1]是此操作写入的最后一个字节。 
该write的方法OutputStream调用写出在每个字节中的一个参数的写入方法。 鼓励子类重写此方法并提供更有效的实现。 

如果b是null ,则抛出NullPointerException 。 

如果off为负,或len为负,或off+len大于数组b的长度,则抛出IndexOutOfBoundsException 。 

参数 
b - 数据。 
off - 数据中的起始偏移量。 
len - 要写入的字节数。 
异常 
IOException - 如果发生I / O错误。 特别是,如果输出流关闭,则抛出IOException 。 
public void write​(byte[] b, int off, int len) throws IOException
将从偏移量off开始的指定字节数组中的len字节写入此输出流。 write(b, off, len)的一般合同是数组b中的一些字节按b写入输出流; element b[off]是写入的第一个字节, b[off+len-1]是此操作写入的最后一个字节。 
该write的方法OutputStream调用写出在每个字节中的一个参数的写入方法。 鼓励子类重写此方法并提供更有效的实现。 

如果b是null ,则抛出NullPointerException 。 

如果off为负,或len为负,或off+len大于数组b的长度,则抛出IndexOutOfBoundsException 。 

参数 
b - 数据。 
off - 数据中的起始偏移量。 
len - 要写入的字节数。 
异常 
IOException - 如果发生I / O错误。 特别是,如果输出流关闭,则抛出IOException 。 

public abstract void write​(int b) throws IOException
将指定的字节写入此输出流。 write的一般合同是将一个字节写入输出流。 要写入的字节是参数b的八个低位。 b的24个高位被忽略。 
OutputStream子类必须提供此方法的实现。 

参数 
b - byte 。 
异常 
IOException - 如果发生I / O错误。 特别是,如果输出流已关闭, IOException可能会抛出IOException 。 
2.1.1.4、nullOutputStream(不常用)
返回一个新的OutputStream ,它丢弃所有字节。 返回的流最初是打开的。 通过调用close()方法关闭流。 对close()后续调用无效。 
虽然流是开放的, write(int) , write(byte[])和write(byte[], int, int)方法什么也不做。 关闭流后,这些方法全部抛出IOException 。 

flush()方法什么都不做。 

结果 
OutputStream ,丢弃所有字节 

2.1.5、FileOutputStream

将程序中的内容写入硬盘

public class Dmo4 {

    public static void main(String[] args) throws IOException {
        //FileOutputStream
        FileOutputStream fos = new FileOutputStream("D//a.txt");
        fos.write(65);
        fos.close();
        System.out.println("已经输入");
    }
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Dmo4 {

    public static void main(String[] args) throws IOException {
        //FileOutputStream
        //true往原有文档内容后面继续加入
        FileOutputStream fos = new FileOutputStream("D//a.txt",true);
        //fos.write(65);
        byte[] bytes = "ABCDEF".getBytes();
        //1:下标,2:显示长度
        fos.write(bytes,1,2);
        fos.close();
        System.out.println("已经输入");
    }
}
2.1.6、FileInputStream

硬盘中的写入程序

2.1.6.1、read
public int read​(byte[] b, int off, int len) throws IOException
从输入流len最多len字节的数据读入一个字节数组。 尝试读取多达len个字节,但可以读取较小的数字。 实际读取的字节数以整数形式返回。 
此方法将阻塞,直到输入数据可用,检测到文件结尾或引发异常。 

如果len为零,则不读取任何字节,并返回0 ; 否则,尝试读取至少一个字节。 如果由于流位于文件末尾而没有可用字节,则返回值-1 ; 否则,至少读取一个字节并存储到b 。 

读取的第一个字节存储在元素b[off] ,下一个存储到b[off+1] ,依此类推。 读取的字节数最多等于len 。 设k为实际读取的字节数; 这些字节将存储在元素b[off]至b[off+ k -1] ,使元素b[off+ k ]至b[off+len-1]不受影响。 

在每种情况下,元素b[0]至b[off]和元素b[off+len]至b[b.length-1]不受影响。 

类InputStream的read(b, off, len)方法只是重复调用方法read() 。 如果第一个此类调用导致IOException ,则从调用read(b, off, len)方法返回该异常。 如果对read()任何后续调用导致IOException ,则会捕获该异常并将其视为文件结束; 读取到该点的字节存储在b并返回异常发生前读取的字节数。 此方法的默认实现将阻塞,直到读取了所请求的输入数据量len ,检测到文件结尾或抛出异常为止。 鼓励子类提供更有效的此方法实现。 

参数 
b - 读取数据的缓冲区。 
off - 数据写入的数组 b中的起始偏移量。 
len - 要读取的最大字节数。 
结果 
读入缓冲区的总字节数,如果由于已到达流末尾而没有更多数据, -1 。 
异常 
IOException - 如果由于文件结尾以外的任何原因无法读取第一个字节,或者输入流已关闭,或者发生某些其他I / O错误。 
NullPointerException - 如果 b是 null 。 
IndexOutOfBoundsException - 如果 off为负数,则 len为负数,或 len为大于 b.length - off 

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo5 {

    public static void main(String[] args) throws IOException {
        //InputStream
        FileInputStream fis = new FileInputStream("D://1.txt");
        /*
        字符逐个输入
        while (true){
            byte b = (byte) fis.read();
            //当为-1时读取完毕
            if(b == -1){
                break;
            }
            System.out.println((char)b);
        }*/
        byte[] bytes = new byte[10];
        int len = fis.read(bytes);
        System.out.println(new String(bytes,0,10));
        len = fis.read(bytes);
        fis.read(bytes);
        System.out.println(new String(bytes,0,10));
        len = fis.read(bytes);
        fis.read(bytes);
        System.out.println(new String(bytes,0,6));

        len = fis.read(bytes);
        System.out.println(len);
        //关闭
        fis.close();
    }
}

2.2、字符输出
2.2.1、方法
2.2.1.1、append
public Writer append​(CharSequence csq, int start, int end) throws IOException
将指定字符序列的子序列追加到此writer。 Appendable 。 
形式的这种方法的调用out.append(csq, start, end)时csq不是null完全相同的方式调用的行为 

   out.write(csq.subSequence(start, end).toString())  Specified by: 
append在界面 Appendable 
参数 
csq - 将附加子序列的字符序列。 如果csq是null ,则将附加字符,就像csq包含四个字符"null" 。 
start - 子序列中第一个字符的索引 
end - 子序列中最后一个字符后面的字符的索引 
结果 
这位作家 
异常 
IndexOutOfBoundsException - 如果 start或 end为负数, start大于 end ,或 end大于 csq.length() IOException - 如果发生I / O错误 

2.2.1.2、write
public abstract void write​(char[] cbuf, int off, int len) throws IOException
写一个字符数组的一部分。 
参数 
cbuf - 字符数组 
off - 开始编写字符的偏移量 
len - 要写入的字符数 
异常 
IndexOutOfBoundsException - 如果 off为负数,或 len为负数,或者 off + len为负数或大于给定数组的长度,则实现应抛出此异常 
IOException - 如果发生I / O错误 
import java.io.FileWriter;
import java.io.IOException;

public class Demo6 {
    //Writer
    public static void main(String[] args) throws IOException {
        //true追加模式
        FileWriter fw = new FileWriter("D://b.txt",true);
        //append调用会返回对象
        //fw.append("床前明月光");
        FileWriter fw2 = (FileWriter) fw.append("汗滴禾下土");
        //此时fw2就是(FileWriter) fw.append("汗滴禾下土")之后的结果,可用fw2继续往fw追加
        fw2.append("锄禾日当午");
        fw.close();
            System.out.println(fw == fw2);

    }
}

2.3、字符输出
2.3.1、方法

read

public abstract int read​(char[] cbuf, int off, int len) throws IOException
将字符读入数组的一部分。 此方法将阻塞,直到某些输入可用,发生I / O错误或到达流的末尾。 
参数 
cbuf - 目标缓冲区 
off - 开始存储字符的偏移量 
len - 要读取的最大字符数 
结果 
读取的字符数,如果已到达流的末尾,则返回-1 
异常 
IOException - 如果发生I / O错误 
IndexOutOfBoundsException - 如果 off为负数,或 len为负数,或 len为大于 cbuf.length - off 

code:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo7 {
    public static void main(String[] args) throws IOException {
        //Reader
        FileReader fr = new FileReader("D://b.txt");
        /*while (true){
            int c = fr.read();
            if (c == -1){
                break;
            }
            System.out.println((char)c);
        }*/
        char[] chars = new char[100];
        //不控制长度,一行后面会加入空格浪费空间
        int len = fr.read(chars);
        System.out.println(new String(chars,0,len));
        fr.close();
    }
}
2.4、flush刷新管道
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo8 {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("D://b.txt");
        fw.append("锄禾日当午").append(",").append("汗滴禾下土");
        //刷新缓存,关闭也是一种刷新缓存,不刷新缓存也不关闭文件,则无法写入信息
        fw.flush();
    }
}

2.5、Print与BufferedReader
import java.io.*;

public class Demo11 {
    public static void main(String[] args) throws IOException {
        //字节输出(打印流)
       /* PrintStream ps = new PrintStream("D://c.txt");
        ps.println("锄禾日当午1");
        ps.println("锄禾日当午2");
        ps.println("锄禾日当午3");
        ps.println("锄禾日当午4");*/

        //字符需要刷新管道
       /* PrintWriter pw = new PrintWriter("D://d.txt");
        pw.println("锄禾日当午1");
        pw.println("锄禾日当午2");
        pw.println("锄禾日当午3");
        pw.println("锄禾日当午4");
        //缓存、刷新管道
        pw.flush();
        */

       /* FileOutputStream fos = new FileOutputStream("D://d.txt");
        PrintWriter pw = new PrintWriter(fos);
        pw.println("锄禾日当午1");
        pw.println("锄禾日当午2");
        pw.println("锄禾日当午3");
        pw.println("锄禾日当午4");
        pw.flush();*/
        //缓存读取流:将字符输入流 转换为带有缓存 可以一次读取一行的缓存字符读取流
        FileReader fw = new FileReader("D://c.txt");
        BufferedReader br = new BufferedReader(fw);
        //读一行.读到最后返回null
        System.out.println(br.readLine());

    }
}

2.6、 收集异常日志
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo12 {
    public static void main(String[] args) throws FileNotFoundException {
        try{
            String s = null;
            s.toString();
        }catch (Exception e){
            PrintWriter pw = new PrintWriter("D://bug.txt");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            pw.println(sdf.format(new Date()));
            //将错误输出至控制台
            e.printStackTrace();
            pw.close();
        }
    }
}

2.7、 properties
import java.io.*;
import java.util.Properties;
//map体系的输入与输出
public class Demo13 {
    public static void main(String[] args) throws IOException {
        /*//.properties文件 与 Properties类
        Properties ppt = new Properties();
        //存入键值对
        ppt.put("name","金苹果");
        ppt.put("info","讲述了苹果种植的过程");
        Writer fw = new FileWriter("D://book.properties");
        //store键值对写入,comments存储注释,不支持中文,支持uincon
        ppt.store(fw,"存储的图书");
        fw.close();*/
        Properties ppt = new Properties();
        Reader r = new FileReader("D://book.text");
        //load加入map转换字节流输出
        ppt.load(r);
        System.out.println(ppt.getProperty("name"));
        System.out.println(ppt.getProperty("info"));
    }
}

2.8、序列化技术
import java.io.*;

public class Demo14 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //序列化 与 反序列化
        /*//序列化
        Book b = new Book("金苹果","描述了苹果");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D://book.txt"));
        oos.writeObject(b);
        oos.close();*/
        //反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D://book.txt"));
        Book o = (Book) ois.readObject();
        System.out.println(o.getInfo());
    }

    //需要定义接口类型,非Serializable类型报错
    static class Book implements Serializable {
        private String name;
        private String info;

        public Book() {
        }

        public Book(String name, String info) {
            this.name = name;
            this.info = info;
        }

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

        public String getName() {
            return name;
        }

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

        public String getInfo() {
            return info;
        }

        public void setInfo(String info) {
            this.info = info;
        }
    }
}
2.8.1、部分属性的序列化和反序列化
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> teacherList = new ArrayList<>();
        teacherList.add("空空道人");
        teacherList.add("贾代儒");
        Student stu = new Student("1001","贾宝玉",teacherList);
        System.out.println("原始对象:" + stu);
        String fileName = "stu01.txt";
        try{
            //对象序列化
            MySerializeUtil.mySerialize(stu,fileName);
            System.out.println("序列化原始对象完成!OK!");
            //对象的反序列化
            Object obj = MySerializeUtil.myDeserialize(fileName);
            if (obj instanceof Student){
                Student stuNew = (Student) obj;
                System.out.println("反序列化之后的对象:" + stuNew);
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

import java.io.*;

public class MySerializeUtil {
    /**
     * 将对象序列化指定到指定文件中
     */
    public static void mySerialize(Object obj,String fileName) throws IOException{
        OutputStream out = new FileOutputStream(fileName);
        ObjectOutputStream objOut = new  ObjectOutputStream(out);
        objOut.writeObject(obj);
        objOut.close();
    }

    public static Object myDeserialize(String fileName) throws IOException,ClassNotFoundException{
        InputStream in = new FileInputStream(fileName);
        ObjectInputStream objIn = new ObjectInputStream(in);
        Object obj = objIn.readObject();
        return obj;
    }
}

import java.io.Serializable;
import java.util.List;

public class Student implements Serializable {
    //学号
    private String stuNum;

    //姓名
    private String stuName;

    //教师姓名:一个学生可以有多个老师
    private List<String> teacherList;

    public Student() {
    }

    public Student(String stuNum, String stuName, List<String> teacherList) {
        this.stuNum = stuNum;
        this.stuName = stuName;
        this.teacherList = teacherList;
    }

    public String getStuNum() {
        return stuNum;
    }

    public void setStuNum(String stuNum) {
        this.stuNum = stuNum;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public List<String> getTeacherList() {
        return teacherList;
    }

    public void setTeacherList(List<String> teacherList) {
        this.teacherList = teacherList;
    }

    @Override
    public String toString() {
        return "Student{" +
                "stuNum='" + stuNum + '\'' +
                ", stuName='" + stuName + '\'' +
                ", teacherList=" + teacherList +
                '}';
    }
}

2.8.2、部分属性的序列化
2.8.2.1、使用transient修饰符

修改实体类,将实体类中不想序列化的属性添加transient修饰词

public class Student implements Externalizable {
private String stuNum;
private transient String stuName;
private transient List<String> tea

重新运行测试类的结果: 我们将实体类中的stuName和teacherList属性添加了transient修饰词,因此对象被序列化的时候忽略 这两个属性。通过运行结果可以看出。

在这里插入图片描述

2.8.2.2、 使用static修饰符

static修饰符修饰的属性也不会参与序列化和反序列化。 修改实体类,将实体类中不想序列化的属性添加static修饰词。

public class Student implements Externalizable {
private String stuNum;
private static String stuName;
private List<String> teacherList;

修改测试类,在完成原始对象的序列化之后再对static修饰的变量进行一次赋值操作:

在这里插入图片描述

重新运行测试类的结果:

我们将实体类中的stuName属性添加了transient修饰词,因此对象被序列化的时候忽略这个属性。通 过运行结果可以看出。
在这里插入图片描述

2.8.3、默认方法writeObject和readObject

修改实体类,将transient修饰词去掉,添加两个方法。

public class Student implements Serializable {
private String stuNum;
private String stuName;
private List<String> teacherList;
private void writeObject(ObjectOutputStream objOut) throws IOException {
System.out.println("writeObject-----------");
objOut.writeObject(stuNum);
objOut.writeObject(stuName);
}
private void readObject(ObjectInputStream objIn) throws IOException,
ClassNotFoundException {
System.out.println("readObject-----------");
stuNum= (String) objIn.readObject();
stuName= (String) objIn.readObject();
}

重新运行测试类的结果: 我们在添加的方法中只对stuNum和stuName属性做了序列化和反序列化的操作,因此只有这个两个属 性可以被序列化和反序列化。

在这里插入图片描述

2.9、try-with-resources
public class Demo15 {
    public static void main(String[] args) throws FileNotFoundException {
        //try-with-resources自动执行close
        //1.7时:
       /* try (FileReader fr = new FileReader("D://book.txt")){
            int c = fr.read();
            System.out.println((char)c);
        } catch (IOException e) {
            e.printStackTrace();
        }*/
        //JDK9进行了优化
       /* FileReader fr = new FileReader("D://book.txt");
        PrintWriter pw = new PrintWriter("D://book.txt");
        try {
            int c = fr.read();
            System.out.print((char)c);
        } catch (IOException e) {
            e.printStackTrace();
        }*/

        try (CloseDemo d = new CloseDemo()){

        }catch (Exception e){

        }
    }
    static class CloseDemo implements Closeable{

        @Override
        public void close() throws IOException {
            System.out.print("方法被调用");
        }
    }
}
结果:方法被调用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值