美文网首页
Java学习笔记7

Java学习笔记7

作者: 海洋_5ad4 | 来源:发表于2018-11-07 22:26 被阅读0次

TreeSet保证元素唯一和自然排序的原理和图解

package com.heima.bean;

public class Person implements Comparable<Person>{
    private String name;
    private int age;    
    public Person() {
        super();
        
    }
    public Person(String name, int age) {
        super();
        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;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    /*@Override
    public boolean equals(Object obj) {
        System.out.println("执行了吗");
        Person p = (Person)obj;
        return this.name.equals(p.name) && this.age == p.age;
    }
    @Override
    public int hashCode() {
        final int NUM = 38;
        return name.hashCode() * NUM + age;
    }*/
    /*
     * 为什么是31?
     * 1,31是一个质数,质数是能被1和自己本身整除的数
     * 2,31这个数既不大也不小
     * 3,31这个数好算,2的五次方-1,2向左移动5位减一
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)    //调用的对象和传入的对象是同一个对象
            return true;    //直接返回true
        if (obj == null)    //传入的对象为null
            return false;   //返回false
        if (getClass() != obj.getClass())   //判断两个对象对应的字节码文件是否是同一个字节码
            return false;                   //如果不是直接返回false
        Person other = (Person) obj;        //向下转型
        if (age != other.age)               //调用对象的年龄不等于传入对象的年龄
            return false;                   //返回false
        if (name == null) {                 //调用对象的姓名为null
            if (other.name != null)         //传入对象的姓名不为null
                return false;               //返回false
        } else if (!name.equals(other.name))//调用对象的姓名不为null,且不等于传入对象的姓名
            return false;                   //返回false
        return true;                        //返回true
    }
    //按照年龄排序
    /*@Override
    public int compareTo(Person o) {
        int num = this.age - o.age;         //年龄是比较的主要条件
        return num == 0 ? this.name.compareTo(o.name) : num;
    }*/
    //按照姓名排序
    /*@Override
    public int compareTo(Person o) {
        int num = this.name.compareTo(o.name);  //姓名是比较的主要条件,字符串的compareTo方法
        return num == 0 ? this.age - o.age : num;
    }*/
    //按照姓名长度排序
    @Override
    public int compareTo(Person o) {
        int length = this.name.length() - o.name.length();      //比较长度为主要条件
        int num = length == 0 ? this.name.compareTo(o.name) : length; //比较内容为次要条件
        return num == 0 ? this.age - o.age : num;           //最后比较年龄
    }
    
    
}
package com.heima.set;

import java.util.TreeSet;

import com.heima.bean.Person;

public class Demo3_TreeSet {

    /**
     * TreeSet集合是用来对元素进行排序的,同样他也可以保证元素的唯一
     * 由于Person没有指定比较,所以需要重写compareTo方法
     * 当compareTo方法返回0的时候集合中只有一个元素
     * 当compareTo方法返回正数的时候集合会怎么存就怎么取
     * 当compareTo方法返回负数的时候集合会倒序存储
     */
    public static void main(String[] args) {
        System.out.println('周' + 0);
        System.out.println('张' + 0);
        System.out.println('李' + 0);
        System.out.println('王' + 0);
        System.out.println('赵' + 0);
        demo2();
    }

    public static void demo2() {
        TreeSet<Person> ts = new TreeSet<>();
        ts.add(new Person("张三11111", 23));
        ts.add(new Person("李四1111", 13));
        ts.add(new Person("周七222", 13));
        ts.add(new Person("王五11", 43));
        ts.add(new Person("赵六1", 33));
        
        System.out.println(ts);
    }

    public static void demo1() {
        TreeSet<Integer> ts = new TreeSet<>();
        ts.add(4);
        ts.add(1);
        ts.add(1);
        ts.add(2);
        ts.add(2);
        ts.add(3);
        ts.add(3);
        
        System.out.println(ts);
    }

}
TreeSet自然排序.jpg

TreeSet保证元素唯一和比较器排序的原理及代码实现

package com.heima.set;

import java.util.Comparator;
import java.util.TreeSet;

import com.heima.bean.Person;

public class Demo3_TreeSet {

    /**
     * TreeSet集合是用来对元素进行排序的,同样他也可以保证元素的唯一
     * 由于Person没有指定比较,所以需要重写compareTo方法
     * 当compareTo方法返回0的时候集合中只有一个元素
     * 当compareTo方法返回正数的时候集合会怎么存就怎么取
     * 当compareTo方法返回负数的时候集合会倒序存储
     */
    public static void main(String[] args) {
        /*System.out.println('周' + 0);
        System.out.println('张' + 0);
        System.out.println('李' + 0);
        System.out.println('王' + 0);
        System.out.println('赵' + 0);*/
        //demo2();
        TreeSet<String> ts = new TreeSet<>(new CompareByLen()); //Comparator c = new CompareByLen()
        ts.add("aaaaaaaa");
        ts.add("z");
        ts.add("wc");
        ts.add("nba");
        ts.add("cba");
        
        System.out.println(ts);
    }

    public static void demo2() {
        TreeSet<Person> ts = new TreeSet<>();
        ts.add(new Person("张三11111", 23));
        ts.add(new Person("李四1111", 13));
        ts.add(new Person("周七222", 13));
        ts.add(new Person("王五11", 43));
        ts.add(new Person("赵六1", 33));
        
        System.out.println(ts);
    }

    public static void demo1() {
        TreeSet<Integer> ts = new TreeSet<>();
        ts.add(4);
        ts.add(1);
        ts.add(1);
        ts.add(2);
        ts.add(2);
        ts.add(3);
        ts.add(3);
        
        System.out.println(ts);
    }

}

class CompareByLen implements Comparator<String> {  
    //由于CompareByLen默认继承Object类,继承了equals方法,所以不用去重写equals方法
    //但是一定要重写compare方法
    @Override               
    public int compare(String s1, String s2) {  //按照字符串长度比较
        int num = s1.length() - s2.length();    //长度为主要条件
        return num == 0 ? s1.compareTo(s2) : num;   //内容为次要条件
    }
    
}
比较器原理.jpg

TreeSet原理

  • 1.特点
    • TreeSet是用来排序的,可以指定一个顺序,对象存入之后会按照指定的顺序排列
  • 2.使用方式
    • a.自然顺序(Comparable)
      • TreeSet类的add()方法中会把存入的对象提升为Comparable类型
      • 调用对象的compareTo()方法和集合中的对象比较
      • 根据compareTo()方法返回的结果进行存储
      • 存入谁谁就会调用compareTo()方法,集合中的元素作为参数传入
    • b.比较器顺序(Comparator)
      • 创建TreeSet的时候可以制定 一个Comparator
      • 如果传入了Comparator的子类对象,那么TreeSet就会按照比较器中的顺序排序
      • add()方法内部会自动调用Comparator接口中compare()方法排序
        *调用add()方法的对象是compare()方法的第一个参数,集合里面的元素就相当于第二个参数
    • c.两种方式的区别
      • TreeSet构造函数什么都不传,默认按照类中Comparable的顺序(没有就报错classCastException)
      • TreeSet如果传入Comparator,就优先按照Comparator

练习

package com.heima.test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

public class Test4 {

    /**
     * 在一个集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且还不能去除重复
     * 1,定义一个List集合,并存储重复的无序的字符串
     * 2,定义方法对其排序保留重复
     * 3,打印List集合
     */
    public static void main(String[] args) {
        //1,定义一个List集合,并存储重复的无序的字符串
        ArrayList<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("aaa");
        list.add("ccc");
        list.add("ddd");
        list.add("fffffffffff");
        list.add("heima");
        list.add("itcast");
        list.add("bbbb");
        list.add("aaa");
        list.add("aaa");
        //2,定义方法对其排序保留重复
        sort(list);
        //3,打印list
        System.out.println(list);
    }
    /*
     * 1,创建TreeSet集合对象,因为String本身就具备比较功能,但是重复不会保留,所以我们用比较器
     * 2,将List集合中所有的元素添加到TreeSet集合中,对其排序,保留重复
     * 3,清空List集合
     * 4,将TreeSet集合中排好序的元素添加到list中
     */
    public static void sort(List<String> list) {
        //1,创建TreeSet集合对象,因为String本身就具备比较功能,但是重复不会保留,所以我们用比较器
        TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
            //匿名内部类
            @Override
            public int compare(String s1, String s2) {
                int num = s1.compareTo(s2);         //比较内容为主要条件
                return num == 0 ? 1 : num;          //保留重复
            }
        });
        //2,将List集合中所有的元素添加到TreeSet集合中,对其排序,保留重复
        ts.addAll(list);
        //3,清空List集合
        list.clear();
        //4,将TreeSet集合中排好序的元素添加到list中
        list.addAll(ts);
        
    }

}
package com.heima.test;

import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

public class Test5 {

    /**
     * 从键盘接收一个字符串,程序对其中所有字符进行排序,例如键盘输入:helloitcast程序打印:acehillostt
     * 1,键盘录入字符串,Scanner
     * 2,将字符串转换为字符数组
     * 3,定义TreeSet集合,传入比较器对字符排序并保留重复
     * 4,遍历字符数组,将每一个字符存储在TreeSet集合中
     * 5,遍历TreeSet集合,打印每一个字符
     */
    public static void main(String[] args) {
        //1,键盘录入字符串,Scanner
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串");
        String line = sc.nextLine();
        //2,将字符串转换为字符数组
        char[] arr = line.toCharArray();
        //3,定义TreeSet集合,传入比较器对字符排序并保留重复
        TreeSet<Character> ts = new TreeSet<>(new Comparator<Character>() {

            @Override
            public int compare(Character c1, Character c2) {
                //int num = c1 - c2;        //自动拆箱
                int num = c1.compareTo(c2);
                return num == 0 ? 1 : num;
            }
        });
        //4,遍历字符数组,将每一个字符存储在TreeSet集合中
        for (char c : arr) {
            ts.add(c);                  //自动装箱
        }
        //5,遍历TreeSet集合,打印每一个字符
        for (Character c : ts) {
            System.out.print(c);
        }
    }

}
package com.heima.test;

import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

public class Test6 {

    /**
     * 程序启动后,可以从键盘输入接收多个整数,直到输入quit时结束输入.把所有输入的整数倒序排列打印.
     * 1,创建Scanner对象,键盘录入
     * 2,创建TreeSet集合对象,TreeSet集合中传入比较器
     * 3,无限循环不断接收整数,遇到quit退出,因为退出是quit,所以键盘录入的时候应该都以字符串的形式录入
     * 4,判断是quit就退出,不是就将其转换为Integer,并添加到集合中
     * 5,遍历TreeSet集合并打印每一个元素
     */
    public static void main(String[] args) {
        //1,创建Scanner对象,键盘录入
        Scanner sc = new Scanner(System.in);
        //2,创建TreeSet集合对象,TreeSet集合中传入比较器
        TreeSet<Integer> ts = new TreeSet<>(new Comparator<Integer>() {

            @Override
            public int compare(Integer i1, Integer i2) {
                //int num = i2 - i1;            //自动拆箱
                int num = i2.compareTo(i1);
                return num == 0 ? 1 : num;
            }
        });
        //3,无限循环不断接收整数,遇到quit退出,因为退出是quit,所以键盘录入的时候应该都以字符串的形式录入
        while(true) {
            String line = sc.nextLine();        //将键盘录入的字符串存储在line中
            //4,判断是quit就退出,不是就将其转换为Integer,并添加到集合中
            if("quit".equals(line)) {
                break;
            }
            Integer i = Integer.parseInt(line);
            ts.add(i);
        }
        //5,遍历TreeSet集合并打印每一个元素
        for (Integer integer : ts) {
            System.out.println(integer);
        }
    }

}
package com.heima.test;

import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

import com.heima.bean.Student;

public class Test7 {

    /**
     * 需求:键盘输入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台。
     * 1,定义一个学生类
     *      成员变量:姓名,语文成绩,数学成绩,英语成绩,总成绩
     *      成员方法:空参,有参构造,有参构造的参数分别是姓名,语文成绩,数学成绩,英语成绩
     *          ToString方法,在遍历集合中的Student对象打印对象引用的时候会显示属性值
     * 2,键盘录入需要Scanner,创建键盘录入对象
     * 3,创建TreeSet集合对象,在TreeSet的构造函数中传入比较器,按照总分比较
     * 4,录入五个学生,所以以集合中的学生个数为判断条件,如果size是小于5就存储
     * 5,将录入的字符串切割,用逗号切割,会返回一个字符串数组,从第二个元素开始,将字符串数组中的元素转换成int数
     * 6,将转换后的结果封装成Student对象,将Student添加到TreeSet集合中
     * 7,遍历TreeSet集合打印每一个Student对象
     */     
    public static void main(String[] args) {
        //2,键盘录入需要Scanner,创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入学生成绩,格式是:姓名,语文成绩,数学成绩,英语成绩");
        //3,创建TreeSet集合对象,在TreeSet的构造函数中传入比较器,按照总分比较
        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {

            @Override
            public int compare(Student s1, Student s2) {
                int num = s2.getSum() - s1.getSum();
                return num == 0 ? 1 : num;
            }
            
        });
        //4,录入五个学生,所以以集合中的学生个数为判断条件,如果size是小于5就存储
        while(ts.size() < 5) {
            //5,将录入的字符串切割,用逗号切割,会返回一个字符串数组,从第二个元素开始,将字符串数组中的元素转换成int数
            String line = sc.nextLine();
            String[] arr = line.split(",");
            int chinese = Integer.parseInt(arr[1]);
            int math = Integer.parseInt(arr[2]);
            int english = Integer.parseInt(arr[3]);
            //6,将转换后的结果封装成Student对象,将Student添加到TreeSet集合中
            ts.add(new Student(arr[0], chinese, math, english));
        }
        //7,遍历TreeSet集合打印每一个Student对象
        System.out.println("排序后的学生信息");
        for (Student s : ts) {
            System.out.println(s);
        }
    }

}

Map集合概述和特点

  • A:Map接口概述
    • 查看API可以知道:
      • 将键映射到值的对象
      • 一个映射不能包含重复的键
      • 每个键最多只能映射到一个值
  • B:Map接口和Collection接口的不同
    • Map是双列的,Collection是单列的
    • Map的键唯一,Collection的子体系Set是唯一的
    • Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效

set底层依赖于map


底层结构.jpg

Map集合的功能概述

  • A:Map集合的功能概述
    • a:添加功能
      • V put(K key,V value):添加元素。
        • 如果键是第一次存储,就直接存储元素,返回null
        • 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
    • b:删除功能
      • void clear():移除所有的键值对元素
      • V remove(Object key):根据键删除键值对元素,并把值返回
    • c:判断功能
      • boolean containsKey(Object key):判断集合是否包含指定的键
      • boolean containsValue(Object value):判断集合是否包含指定的值
      • boolean isEmpty():判断集合是否为空
    • d:获取功能
      • Set<Map.Entry<K,V>> entrySet():
      • V get(Object key):根据键获取值
      • Set<K> keySet():获取集合中所有键的集合
      • Collection<V> values():获取集合中所有值的集合
    • e:长度功能
      • int size():返回集合中的键值对的个数
package com.heima.map;

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

public class Demo1_Map {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("张三",23);
        map.put("李四",24);
        map.put("王五",25);
        map.put("赵六", 23);
        
        Collection<Integer> c = map.values();
        System.out.println(c);
        System.out.println(map.size());
    }

    public static void demo2() {
        Map<String, Integer> map = new HashMap<>();
        map.put("张三",23);
        map.put("李四",24);
        map.put("王五",25);
        map.put("赵六", 23);
        Integer value = map.remove("张三");   //根据键删除元素,返回键对应的值
        System.out.println(value);
        System.out.println(map.containsKey("张三"));  //判断是否包含传入的键
        System.out.println(map.containsValue(100)); //判断是否包含传入的值
        System.out.println(map);
    }

    public static void demo1() {
        Map<String, Integer> map = new HashMap<>();
        Integer i1 = map.put("张三", 23);
        Integer i2 = map.put("李四", 24);
        Integer i3 = map.put("王五", 25);
        Integer i4 = map.put("赵六", 26);
        Integer i5 = map.put("张三", 26);     //put方法返回的是被覆盖的值
        
        System.out.println(map);
        System.out.println(i1);
        System.out.println(i2);
        System.out.println(i3);
        System.out.println(i4);
        System.out.println(i5);
    }

}

Map集合的遍历之键找值

  • A:键找值思路:
    • 获取所有键的集合
    • 遍历键的集合,获取到每一个键
    • 根据键找值
package com.heima.map;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Demo2_Iterator {

    /**
     * 通过查看Map集合的api发现没有iterator方法,那么双列集合如何迭代呢?
     */
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("张三",23);
        map.put("李四",24);
        map.put("王五",25);
        map.put("赵六", 26);
        
        Integer i = map.get("111"); //根据键获取值,若没有返回null
        System.out.println(i);
        //获取所有的键
        /*Set<String> keySet = map.keySet();    //获取所有键的集合
        Iterator<String> it = keySet.iterator();    //获取迭代器
        while(it.hasNext()) {                       //判断集合中是否有元素
            String key = it.next();                 //获取每一个键
            Integer value = map.get(key);           //根据键获取值
            System.out.println(key + "=" + value);
        }*/
        
        //使用增强for循环遍历
        for (String key : map.keySet()) {           //map.keySet()是所有键的集合
            System.out.println(key + "=" + map.get(key));
        }
    }

}

Map集合的遍历之键值对对象找键和值

  • A:键值对对象找键和值思路:
    • 获取所有键值对对象的集合(把双列集合的键值对变成单列集合的键值对对象)
    • 遍历键值对对象的集合,获取到每一个键值对对象
    • 根据键值对对象找键和值
package com.heima.map;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Demo3_Iterator {

    /**
     * Entry实现了Map.Entry
     */
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("张三",23);
        map.put("李四",24);
        map.put("王五",25);
        map.put("赵六", 26);
        //Map.Entry说明Entry是Map的内部接口,将键和值封装成Entry对象,并存储在Set集合中
        /*Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        //获取每一个对象
        Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
        while(it.hasNext()) {
            //获取每一个Entry对象
            Map.Entry<String, Integer> en = it.next();  //父类引用指向子类对象
            //Entry<String, Integer> en = it.next();        //直接获取子类对象
            String key = en.getKey();                   //根据键值对对象获取键
            Integer value = en.getValue();              //根据键值对对象获取值
            System.out.println(key + "=" + value);
        }*/
        for (Map.Entry<String, Integer> en : map.entrySet()) {  
            System.out.println(en.getKey() + "=" + en.getValue());
        }
        
    }

}
package com.heima.map;

import java.util.HashMap;

import com.heima.bean.Student;

public class Demo5_HashMap {

    /**
     * HashMap集合键是Student值是String的案例
     */
    public static void main(String[] args) {
        HashMap<Student, String> hm = new HashMap<>();
        hm.put(new Student("张三", 23), "北京");
        hm.put(new Student("张三", 23), "上海");
        hm.put(new Student("李四", 23), "广州");
        hm.put(new Student("王五", 23), "深圳");
        
        System.out.println(hm);
    }

}

LinkedHashMap的概述和使用

package com.heima.map;

import java.util.LinkedHashMap;

public class Demo6_LinkedHashMap {

    /**
     * 底层是链表实现的可以保证怎么存就怎么取
     */
    public static void main(String[] args) {
        LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
        lhm.put("张三", 23);
        lhm.put("李四", 24);
        lhm.put("赵六", 25);
        lhm.put("王五", 26);
        System.out.println(lhm);
    }

}

TreeMap集合键是Student值是String的案例

package com.heima.map;

import java.util.Comparator;
import java.util.TreeMap;

import com.heima.bean.Student;

public class Demo7_TreeMap {

    /**
     * @param args
     */
    public static void main(String[] args) {
        TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {

            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getName().compareTo(s2.getName()); //按照姓名比较
                return num == 0 ? s1.getAge() - s2.getAge() : num;
            }
        });
        tm.put(new Student("李四", 13), "上海");
        tm.put(new Student("张三", 23), "北京");    //TreeMap需要对键有比较的方法
        tm.put(new Student("王五", 33), "广州");    //或者传入比较器
        tm.put(new Student("赵六", 43), "深圳");
        System.out.println(tm);
    }

    public static void demo1() {
        TreeMap<Student, String> tm = new TreeMap<>();
        tm.put(new Student("张三", 23), "北京");    //TreeMap需要对键有比较的方法
        tm.put(new Student("李四", 13), "上海");    //需要重写对象的compareTo方法
        tm.put(new Student("王五", 33), "广州");
        tm.put(new Student("赵六", 43), "深圳");
        System.out.println(tm);
    }

}

统计字符串中每个字符出现的次数

package com.heima.test;

import java.util.HashMap;

public class Test1 {

    /**
     * 需求:统计字符串中每个字符出现的次数
     * 1,定义一个需要被统计字符的字符串
     * 2,将字符串转换为字符数组
     * 3,定义双列集合,存储字符串中字符以及字符出现的次数
     * 4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
     * 5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,否则就将值加一
     * 6,打印双列集合获取字符出现的次数
     */
    public static void main(String[] args) {
        //1,定义一个需要被统计字符的字符串
        String s = "aaaabbbbbccccccccccccc";
        //2,将字符串转换为字符数组
        char[] arr = s.toCharArray();
        //3,定义双列集合,存储字符串中字符以及字符出现的次数
        HashMap<Character, Integer> hm = new HashMap<>();
        //4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
        for(char c: arr) {
            //5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,否则就将值加一
            /*if(!hm.containsKey(c)) {  //如果不包含这个键
                hm.put(c, 1);
            }else {
                hm.put(c, hm.get(c) + 1);
            }*/
            hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
        }
        //6,打印双列集合获取字符出现的次数
        //System.out.println(hm);
        for (Character key : hm.keySet()) {         //hm.keySet()代表所有键的集合
            System.out.println(key + "=" + hm.get(key));    //hm.get(key)根据键获取值
        }
    }

}

集合嵌套之HashMap嵌套HashMap

package com.heima.map;

import java.util.HashMap;

import com.heima.bean.Student;

public class Demo8_HashMapHashMap {

    /**
     * 需求:
     * 双元课堂有很多基础班
     * 第88期基础班定义成一个双列集合,键是学生对象。值是学生的归属地
     * 第99期基础班定义成一个双列集合,键是学生对象。值是学生的归属地
     * 无论88期还是99期都是班级对象,所以为了便于统一管理,把这些班级对象添加到双元课堂集合中
     */
    public static void main(String[] args) {
        //定义88期基础班
        HashMap<Student, String> hm88 = new HashMap<>();
        hm88.put(new Student("张三", 23), "北京");
        hm88.put(new Student("李四", 24), "北京");
        hm88.put(new Student("王五", 25), "上海");
        hm88.put(new Student("赵六", 26), "广州");
        
        //定义99期基础班
        HashMap<Student, String> hm99 = new HashMap<>();
        hm99.put(new Student("唐僧", 23), "北京");
        hm99.put(new Student("孙悟空", 24), "北京");
        hm99.put(new Student("猪八戒", 25), "上海");
        hm99.put(new Student("沙和尚", 26), "广州");
        
        //定义双元课堂
        HashMap<HashMap<Student, String>, String> hm = new HashMap<>();
        hm.put(hm88, "第88期基础班");
        hm.put(hm99, "第99期基础班");
        
        //遍历双列集合
        for (HashMap<Student, String> h : hm.keySet()) {    //hm.keySet()代表的是双列集合中键的集合
            String value = hm.get(h);                       //get(h)根据键对象获取值对象
            //遍历键的双列集合对象    
            for (Student student : h.keySet()) {            //h.keySet()获取集合中所有的键(学生)对象
                String value2 = h.get(student);
                
                System.out.println(student + "=" + value2 + "=" + value);
            }
        }
    }

}

HashMap和Hashtable的区别

  • A:面试题
    • HashMap和Hashtable的区别
      • Hashtable是JDK1.0版本出现的,是线程安全的,效率低,HashMap是JDK1.2版本出现的,是线程不安全的,效率高
      • Hashtable不可以存储null键和null值,HashMap可以存储null键和null值
package com.heima.map;

import java.util.HashMap;
import java.util.Hashtable;

public class Demo9_Hashtable {

    /**
     * 面试题
     * HashMap和Hashtable的区别
     * 共同点:
     * 底层都是哈希算法,都是双列集合
     */
    public static void main(String[] args) {
        /*HashMap<String, Integer> hm = new HashMap<>();
        hm.put(null, null); 
        hm.put("张三", null);
        hm.put(null,23);
        System.out.println(hm);*/
        
        Hashtable<String, Integer> ht = new Hashtable<>();
        ht.put("张三", 23);
        //ht.put(null, 24); //NullPointerException
        ht.put("李四", null);//NullPointerException
        System.out.println(ht);
    }

}

Collections工具类的概述和常见方法讲解

package com.heima.collections;

import java.util.ArrayList;
import java.util.Collections;

public class Demo1_Collections {

    /**
     *  public static <T> void sort(List<T> list)
        public static <T> int binarySearch(List<?> list,T key)
        public static <T> T max(Collection<?> coll)
        public static void reverse(List<?> list)
        public static void shuffle(List<?> list)
     */
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("c");
        list.add("a");
        list.add("d");
        list.add("g");
        list.add("f");
        System.out.println(Collections.max(list));  //根据默认排序结果获取集合中的最大值
        Collections.reverse(list);                  //反转集合
        System.out.println(list);
        Collections.shuffle(list);                  //随机置换,可以用来洗牌
        System.out.println(list);   
    }

    public static void demo2() {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("c");
        list.add("d");
        list.add("f");
        list.add("g");
        
        System.out.println(Collections.binarySearch(list,"c"));
        System.out.println(Collections.binarySearch(list,"b")); //负的插入点减一
    }

    public static void demo1() {
        ArrayList<String> list = new ArrayList<>();
        list.add("c");
        list.add("a");
        list.add("a");
        list.add("b");
        list.add("d");
        
        System.out.println(list);   //[c, a, a, b, d]
        Collections.sort(list);     //将集合排序
        System.out.println(list);   //[a, a, b, c, d]
    }

}

模拟斗地主洗牌和发牌

package com.heima.test;

import java.util.ArrayList;
import java.util.Collections;

public class Test2 {
    public static void main(String[] args) {
        //1,买一副扑克,其实就是自己创建一个集合对象,将扑克牌存储进去
        String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
        String[] color = {"红桃","黑桃","方片","梅花"};
        ArrayList<String> poker = new ArrayList<>();
        
        //拼接花色和数字
        for (String s1 : color) {
            for (String s2 : num) {
                poker.add(s1.concat(s2));   //concat连接两个字符串
            }
        }
        poker.add("小王");
        poker.add("大王");
        //System.out.println(poker);
        //2,洗牌
        Collections.shuffle(poker);
        //System.out.println(poker);
        //3,发牌
        ArrayList<String> gaojin = new ArrayList<>();
        ArrayList<String> longwu = new ArrayList<>();
        ArrayList<String> me = new ArrayList<>();
        ArrayList<String> dipai = new ArrayList<>();
        
        for (int i = 0; i < poker.size(); i++) {
            if(i >= poker.size() - 3) {
                dipai.add(poker.get(i));
            } else if(i % 3 == 0) {
                gaojin.add(poker.get(i));
            } else if(i % 3 == 2) {
                longwu.add(poker.get(i));
            } else {
                me.add(poker.get(i));
            }
        }
        //4,看牌
        System.out.println(me);
        System.out.println(gaojin);
        System.out.println(longwu);
        System.out.println(dipai);
    }

}

模拟斗地主洗牌和发牌并对牌进行排序

斗地主.png
package com.heima.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

public class Test3 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //1,买一副扑克,其实就是自己创建一个集合对象,将扑克牌存储进去
        String[] num = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
        String[] color = {"红桃","黑桃","方片","梅花"};
        HashMap<Integer, String> hm = new HashMap<>();
        ArrayList<Integer> list = new ArrayList<>();
        int index = 0;
        //拼接扑克牌并将他们存在hm中
        for (String s1 : num) {
            for (String s2 : color) {
                hm.put(index, s2.concat(s1));
                list.add(index);
                index++;
            }
        }
        //将大小王添加到双列集合中
        hm.put(index, "小王");
        list.add(index);
        index++;
        hm.put(index, "大王");
        list.add(index);
        //System.out.println(hm);
        //System.out.println(list);
        //2,洗牌
        Collections.shuffle(list);
        //3,发牌
        TreeSet<Integer> gaojin = new TreeSet<>();
        TreeSet<Integer> longwu = new TreeSet<>();
        TreeSet<Integer> me = new TreeSet<>();
        TreeSet<Integer> dipai = new TreeSet<>();
        
        for (int i = 0; i < list.size(); i++) {
            if(i >= list.size() - 3) {
                dipai.add(list.get(i));         //将三张底牌存储在底牌集合中
            }else if(i % 3 == 0) {
                gaojin.add(list.get(i));
            }else if(i % 3 == 1) {
                longwu.add(list.get(i));
            }else {
                me.add(list.get(i));
            }
        }
        //看牌
        lookPoker(hm,gaojin,"高进");
        lookPoker(hm,gaojin,"龙五");
        lookPoker(hm,me,"aaa");
        lookPoker(hm,dipai,"底牌");
    }
    
    public static void lookPoker(HashMap<Integer, String> hm,TreeSet<Integer> ts
            ,String name) {
        System.out.print(name + "的牌是");
        for (Integer i : ts) {                  //i代表双列集合中的每一个键
            System.out.print(hm.get(i) + " ");
        }
        System.out.println();
    }
}

泛型固定下边界

package com.heima.collections;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.TreeSet;

import com.heima.bean.BaseStudent;
import com.heima.bean.Student;

public class Demo2_Genric {

    /**
     * 泛型固定下边界
     * ? super E
     * 泛型固定上边界
     * ? extends E
     * 都是父类引用指向子类对象
     */
    public static void main(String[] args) {
        TreeSet<Student> ts1 = new TreeSet<>(new CompareByAge());
        ts1.add(new Student("张三",33));
        ts1.add(new Student("李四",13));
        ts1.add(new Student("王五",23));
        ts1.add(new Student("赵六",43));
        
        TreeSet<BaseStudent> ts2 = new TreeSet<>(new CompareByAge());
        ts2.add(new BaseStudent("张三",33));
        ts2.add(new BaseStudent("李四",13));
        ts2.add(new BaseStudent("王五",23));
        ts2.add(new BaseStudent("赵六",43));
        System.out.println(ts2);    //? super E     将子类对象放进比较器作比较
    }

    public static void demo1() {
        ArrayList<Student> list1 = new ArrayList<>();
        list1.add(new Student("张三", 23));
        list1.add(new Student("李四", 24));
        
        ArrayList<BaseStudent> list2 = new ArrayList<>();
        list2.add(new BaseStudent("张三", 23));
        list2.add(new BaseStudent("李四", 24));
        
        list1.addAll(list2);    //? extends E    将子类对象储存在父类数组中
    }

}

class CompareByAge implements Comparator<Student> {

    @Override
    public int compare(Student s1, Student s2) {
        int num = s1.getAge() - s2.getAge();
        return num == 0 ? s1.getName().compareTo(s2.getName()) : num;
    }
    
}

总结

package com.heima.collections;

public class Demo3_Collection {

    /**
     * Collection
     *      List(存取有序,有索引,可以重复)
     *          ArrayList
     *              底层是数组实现的,线程不安全,查找和修改快,增和删比较慢
     *          LinkedList
     *              底层是链表实现的,线程不安全,增和删比较快,查找和修改比较慢
     *          Vector
     *              底层是数组实现的,线程安全的,无论增删改查都慢
     *          如果查找和修改多,用ArrayList
     *          如果增和删多,用LinkedList
     *          如果都多,用ArrayList
     *      Set(存取无序,无索引,不可以重复)
     *          HashSet
     *              底层是哈希算法实现
     *              LinkedHashSet
     *                  底层是链表实现,但是也是可以保证元素唯一,和HashSet原理一样
     *          TreeSet
     *              底层是二叉树算法实现
     *          一般在开发的时候不需要对存储的元素排序,所以在开发的时候大多用HashSet,HashSet的效率比较高
     *          TreeSet在面试的时候比较多,问你有几种排序方式,和几种排序方式的区别
     * Map
     *      HashMap
     *          底层是哈希算法,针对键
     *          LinkedHashMap
     *              底层是链表,针对键
     *      TreeMap
     *          底层是二叉树算法,针对键
     *      开发中用HashMap比较多
     */
    public static void main(String[] args) {

    }

}

异常的概述和分类

  • A:异常的概述
    • 异常就是Java程序在运行过程中出现的错误。
  • B:异常的分类
    • 通过API查看Throwable
    • Error
      • 服务器宕机,数据库崩溃等
    • Exception
  • C:异常的继承体系
    • Throwable
      • Error
      • Exception
        • RuntimeException

JVM默认是如何处理异常的

  • A:JVM默认是如何处理异常的
    • main函数收到这个问题时,有两种处理方式:
    • a:自己将该问题处理,然后继续运行
    • b:自己没有针对的处理方式,只有交给调用main的jvm来处理
    • jvm有一个默认的异常处理机制,就将该异常进行处理.
    • 并将该异常的名称,异常的信息.异常出现的位置打印在了控制台上,同时将程序停止运行
package com.heima.exception;

public class Demo1_Exception {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Demo d = new Demo();
        int x = d.div(10, 0);
        System.out.println(x);
    }

}

class Demo {
    public int div(int a, int b) {  //10 / 0被除数是10,除数是0当除数是0的时候违背算术运算法则,抛出异常
        return a / b;               //new ArithmeticException("/ by zero");返回这样一个对象
    }
}

try...catch的方式处理异常1

  • A:异常处理的两种方式
    • a:try…catch…finally
      • try catch
      • try catch finally
      • try finally
    • b:throws
  • B:try...catch处理异常的基本格式
    • try…catch…finally
package com.heima.exception;

public class Demo2_Exception {

    /**
     * try:用来检测异常的
     * catch:用来捕获异常
     * finally:释放资源
     * 当通过trycatch将问题处理了,程序会继续执行
     */
    public static void main(String[] args) {
        Demo2 d = new Demo2();
        try {
            int x = d.div(10, 0);
            System.out.println(x);
        }catch(ArithmeticException a) {         //ArithmeticException a = new ArithmeticException();
            System.out.println("出错了,除数为零了");
        }
        System.out.println("继续执行");
    }

}

class Demo2 {                       //不能在同一个包下有两个相同名字的类
    public int div(int a, int b) {  //10 / 0被除数是10,除数是0当除数是0的时候违背算术运算法则,抛出异常
        return a / b;               //new ArithmeticException("/ by zero");返回这样一个对象
    }
}

try...catch的方式处理异常2

  • A:案例演示
    • try...catch的方式处理多个异常
    • JDK7以后处理多个异常的方式及注意事项
package com.heima.exception;

public class Demo3_Exception {
//安卓,服务端开发,如何处理异常?try{}catch(Exception e){}
//ee,服务端开发,一般都是底层开发,从底层向上抛
//try后面如果跟多个catch,那么小的异常放前面,大的异常放后面,根据多态的原理,如果大的放前面,
//就会将所有的子类对象接收,后面的catch就没有意义了
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        int[] arr = {11,22,33,44,55};
        //JDK如何处理多个异常
        try {
            System.out.println(a / b);
            System.out.println(arr[10]);
        } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
            System.out.println("出错了");
        }
    }

    public static void demo1() {
        int a = 10;
        int b = 0;
        int[] arr = {11,22,33,44,55};
        
        try {
            //System.out.println(a / b);
            //System.out.println(arr[10]);
            arr = null;
            System.out.println(arr[0]);
        } catch (ArithmeticException e) {
            System.out.println("除数不能为零");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("索引越界了");
        } catch (Exception e) {             //Exception e = new NullPointerExcption();
            System.out.println("出错了");      //父类引用指向子类对象
        }
        
        System.out.println("over");
    }

}

编译期异常和运行期异常的区别

  • A:编译期异常和运行期异常的区别
    • Java中的异常被分为两大类:编译时异常和运行时异常。

    • 所有的RuntimeException类及其子类的实例被称为运行时异常,其他的异常就是编译时异常

    • 编译时异常

      • Java程序必须显示处理,否则程序就会发生错误,无法通过编译
    • 运行时异常

      • 无需显示处理,也可以和编译时异常一样处理
package com.heima.exception;

import java.io.FileInputStream;

public class Demo4_Exception {

    /**
     * 编译时异常有点未雨绸缪的味道(不规范的说法)
     * 编译时异常:在编译某个程序的时候,有可能会有一些事情发生,比如文件找不到,这样的异常就必须在编译的时候
     * 处理,如果不处理编译通不过    //自己的理解:就是语法不合符规范
     * 运行时异常:就是程序员所犯得错误,需要回来修改代码    //自己的理解:就是语法符合规范,但是程序逻辑错误
     * 这里的逻辑指的是空指针、除以0等
     */
    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("xxx.txt");
        } catch(Exception e) {
            System.out.println(1);
        }
    }

}

Throwable的几个常见方法

  • A:Throwable的几个常见方法
    • a:getMessage()
      • 获取异常信息,返回字符串。
    • b:toString()
      • 获取异常类名和异常信息,返回字符串。
    • c:printStackTrace()
      • 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
package com.heima.exception;

public class Demo5_Throwable {

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            System.out.println(1/0);
        } catch (Exception e) {     //Exception e = new ArithmeticException("/by zero")
            System.out.println(e.getMessage());     //获取异常信息
            System.out.println(e);  //调用toString方法,打印异常类名和异常信息
            e.printStackTrace();    //JVM默认用这种方式处理异常
        }
    }

}

throws的方式处理异常

  • A:throws的方式处理异常
    • 定义功能方法时,需要把出现的问题暴露出来让调用者去处理。
    • 那么就通过throws在方法上标识。
package com.heima.exception;

public class Demo6_Exception {

    /**
     * 编译时异常的抛出必须对其进行处理
     * 运行时异常的抛出可以处理也可以不处理
     */
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        p.setAge(-17);
        System.out.println(p.getAge());
    }

}

class Person {
    private String name;
    private int age;
    public Person() {
        super();
        
    }
    public Person(String name, int age) {
        super();
        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) throws Exception {
        if(age > 0 && age <= 150) {
            this.age = age;
        }else {
            throw new Exception("年龄非法");//这里是匿名对象,也可以抛出有名字的对象。
        }   
    }
    
}

throw的概述以及和throws的区别

  • A:throw的概述
    • 在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。
  • C:throws和throw的区别
    • a:throws
      • 用在方法声明后面,跟的是异常类名
      • 可以跟多个异常类名,用逗号隔开
      • 表示抛出异常,由该方法的调用者来处理
    • b:throw
      • 用在方法体内,跟的是异常对象名
      • 只能抛出一个异常对象名
      • 表示抛出异常,由方法体内的语句处理

finally关键字的特点及作用

A:finally的特点
* 被finally控制的语句体一定会执行
* 特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))

  • B:finally的作用
    • 用于释放资源,在IO流操作和数据库操作中会见到
package com.heima.exception;

public class Demo7_Finally {

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            System.out.println(10/0);
        } catch (Exception e){
            System.out.println("除数为零了");
            System.exit(0);     //退出java虚拟机
            return;     //会先执行finally
        } finally {
            System.out.println("看看我执行了吗");  //即使有return语句也会先执行finally
        }
    }

}

finally关键字的面试题

package com.heima.test;

public class Test1 {

    /**
    * * A:面试题1
        * final,finally和finalize的区别
        * final可以修饰类,不能被继承
        * 修饰方法,不能被重写
        * 修饰变量,只能赋值一次
        * 
        * finally是try语句中的一个语句体,不能单独使用,用来释放资源
        * 
        * finalize是一个方法,当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
    * * B:面试题2
        * 如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问是在return前还是return后。
        * 无论try里执行了return语句、break语句、还是continue语句,finally语句块还会继续执行
        * 如果try语句里有return,那么代码的行为如下:
            1.如果有返回值,就把返回值保存到局部变量中
            2.执行jsr指令跳到finally语句里执行
            3.执行完finally语句后,返回之前保存在局部变量表里的值
     */
    public static void main(String[] args) {
        Demo d = new Demo();
        System.out.println(d.method());
    }

}

class Demo {
    public int method() {
        int x = 10;
        try {
            x = 20;
            System.out.println(1/0);
            return x;
        } catch (Exception e) {
            x =30;
            return x;
        } finally {
            x = 40;     //如果finally有return,会覆盖之前的return方法,不要在里面写return语句
        }
    }
}

自定义异常概述和基本使用

B:自定义异常概述
* 继承自Exception
* 继承自RuntimeException

package com.heima.exception;

public class Demo8_Exception {

    /**
     * 自定义异常原因:通过名字区分到底是什么异常,有针对的解决办法
     */
    public static void main(String[] args) {

    }

}

class AgeOutOfBoundsException extends Exception {

    public AgeOutOfBoundsException() {
        super();
        
    }

    public AgeOutOfBoundsException(String message) {
        super(message);
        
    }
    
}

异常的注意事项及如何使用异常处理

  • A:异常注意事项
    • a:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
    • b:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
    • c:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws
  • B:如何使用异常处理
    • 原则:如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这是用throws

    • 区别:

      • 后续程序需要继续运行就try
      • 后续程序不需要继续运行就throws
    • 如果JDK没有提供对应的异常,需要自定义异常。

练习

package com.heima.test;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;

public class Test2 {

    /**
     * 键盘录入一个int类型的整数,对其求二进制表现形式
     * 如果录入的整数过大,给予提示,录入的整数过大请重新录入一个整数BigInteger
     * 如果录入的是小数,给予提示,录入的是小数,请重新录入一个整数
     * 如果录入的是其他字符,给予提示,录入的是非法字符,请重新录入一个整数
     * 
     * 分析:
     * 1,创建键盘录入对象
     * 2,将键盘录入的结果存储在String类型的字符串中,存储int类型中如果有不符合条件的直接报错,无法进行后续判断
     * 3,键盘录入的结果转换成int类型的数据,是正确的还是错误的
     * 4,正确的直接转换
     * 5,错误的要进行对应判断
     * Alt+shitf+z  (try catch代码块快捷键)
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个整数:");
            
        while(true) {
            String line = sc.nextLine();            //将键盘录入的结果存储在line中
            try {
                int num = Integer.parseInt(line);           //将字符串转换为整数
                System.out.println(Integer.toBinaryString(num));//将整数转换为二进制
                break;                                      //跳出循环
            }catch(Exception e) {
                try {
                    new BigInteger(line);
                    System.out.println("录入错误,您录入的是一个过大整数,请重新输入一个整数");
                } catch (Exception e1) {
                    try {
                        new BigDecimal(line);
                        System.out.println("录入错误,您录入的是一个小数,请重新输入一个整数");
                    } catch (Exception e2) {
                        System.out.println("录入错误,您录入的是非法字符,请重新输入一个整数");
                    }
                }
            }
        }
    }

}

File类的概述和构造方法

  • A:File类的概述
    • File更应该叫做一个路径
      • 文件路径或者文件夹路径
      • 路径分为绝对路径和相对路径
      • 绝对路径是一个固定的路径,从盘符开始
      • 相对路径相对于某个位置,在eclipse下是指当前项目下,在dos下
    • 查看API指的是当前路径
    • 文件和目录路径名的抽象表示形式
  • B:构造方法
    • File(String pathname):根据一个路径得到File对象
    • File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
    • File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象
package com.heima.file;

import java.io.File;

public class Demo1_File {

    public static void main(String[] args) {
        File parent =  new File("D:\\BaiduNetdiskDownload\\01-JavaSE知识(学习27天)\\day01(计算机基础知识&jdk安装&标识符)");
        String child = "01.01_计算机基础知识(计算机概述)_rec.avi";
        File file = new File(parent, child);
        System.out.println(file.exists());
        System.out.println(parent.exists());
    }

    public static void demo2() {
        String parent =  "D:\\BaiduNetdiskDownload\\01-JavaSE知识(学习27天)\\day01(计算机基础知识&jdk安装&标识符)";
        String child = "01.01_计算机基础知识(计算机概述)_rec.avi";
        File file = new File(parent, child);
        System.out.println(file.exists());
    }

    public static void demo1() {
        File file = new File("D:\\BaiduNetdiskDownload\\01-JavaSE知识(学习27天)" +
                "\\day01(计算机基础知识&jdk安装&标识符)\\01.01_计算机基础知识(计算机概述)_rec.avi");
        System.out.println(file.exists());
        
        File file2 = new File("xxx.txt");
        System.out.println(file2.exists());
        
        File file3 = new File("yyy.txt");
        System.out.println(file3.exists());
    }

}

File类的创建功能

  • A:创建功能
    • public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
    • public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
    • public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来
    • 注意事项:
      • 如果你创建文件或者文件夹忘了写盘符路径,那么,默认在项目路径下
package com.heima.file;

import java.io.File;
import java.io.IOException;

public class Demo2_FileMethod {

    /**
     * @param args
     *  
     */
    public static void main(String[] args) throws IOException {
        File dir1 = new File("aaa");
        System.out.println(dir1.mkdir());
        
        File dir2 = new File("bbb.txt");        //这样写是可以的,文件夹可以有后缀名
        System.out.println(dir2.mkdir());
        
        File dir3 = new File("ccc\\ddd");
        System.out.println(dir3.mkdirs());      //创建多级目录
    }

    public static void demo1() throws IOException {
        File file = new File("yyy.txt");
        System.out.println(file.createNewFile());   //如果没有就创建,返回true,否则就不创建,返回false
        
        File file2 = new File("zzz");   //没有格式的也可以创建
        System.out.println(file2.createNewFile());
    }

}

File类的重命名和删除功能

  • A:重命名和删除功能
    • public boolean renameTo(File dest):把文件重命名为指定的文件路径
    • public boolean delete():删除文件或者文件夹
  • B:重命名注意事项
    • 如果路径名相同,就是改名。
    • 如果路径名不同,就是改名并剪切。
  • C:删除注意事项:
    • Java中的删除不走回收站。
    • 要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹
package com.heima.file;

import java.io.File;

public class Demo3_FileMethod {

    /**
     * @param args
     */
    public static void main(String[] args) {
        File file1 = new File("yyy.txt");
        System.out.println(file1.delete());
        
        File file2 = new File("aaa");
        System.out.println(file2.delete());
        
        File file3 = new File("ccc");           //如果删除一个文件夹,那么这个文件夹必须是空的
        System.out.println(file3.delete());
    }

    public static void demo1() {
        File file1 = new File("ooo.txt");
        File file2 = new File("D:\\xxx.txt");
        System.out.println(file1.renameTo(file2));
    }

}

File类的判断功能

  • A:判断功能
    • public boolean isDirectory():判断是否是目录
    • public boolean isFile():判断是否是文件
    • public boolean exists():判断是否存在
    • public boolean canRead():判断是否可读
    • public boolean canWrite():判断是否可写
    • public boolean isHidden():判断是否隐藏
package com.heima.file;

import java.io.File;

public class Demo4_FileMethod {

    public static void main(String[] args) {
        File file = new File("zzz");
        file.setReadable(false);                
        System.out.println(file.canRead());     //windows系统认为所有的文件都是可读的,一定会返回true
        file.setWritable(false);
        System.out.println(file.canWrite());    //windows系统可以设置为不可写
    }

    public static void demo1() {
        File dir1 = new File("ccc");
        System.out.println(dir1.isDirectory());     //判断是否是文件夹
        
        File dir2 = new File("zzz");
        System.out.println(dir2.isDirectory());
        
        System.out.println(dir1.isFile());          //判断是否是文件
        System.out.println(dir2.isFile());
    }

}

File类的获取功能

  • A:获取功能
    • public String getAbsolutePath():获取绝对路径
    • public String getPath():获取路径
    • public String getName():获取名称
    • public long length():获取长度。字节数
    • public long lastModified():获取最后一次的修改时间,毫秒值
    • public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
    • public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组
package com.heima.file;

import java.io.File;
import java.util.Date;

public class Demo5_FileMethod {

    public static void main(String[] args) {
        File dir = new File("D:/BaiduNetdiskDownload/01-JavaSE知识(学习27天)");
        String[] arr = dir.list();      //仅为了获取文件名
        for (String string : arr) {
            System.out.println(string);
        }
        
        File[] subFiles = dir.listFiles();  //获取文件对象
        
        for (File file : subFiles) {
            System.out.println(file);
        }
    }

    public static void demo1() {
        File file1 = new File("xxx.txt");
        File file2 = new File("D:\\双元课堂\\day19\\xxx.txt");
        System.out.println(file1.getAbsolutePath());    //获取绝对路径
        System.out.println(file2.getAbsolutePath());
        System.out.println(file1.getPath());            //获取构造方法中传入的路径
        System.out.println(file2.getPath());
        System.out.println(file1.getName());            //获取文件或文件夹的名字
        System.out.println(file2.getName());
        System.out.println(file1.length());
        System.out.println(file1.lastModified());       //文件的最后修改时间
        Date d = new Date(file1.lastModified());
        System.out.println(d);
    }

}

输出指定目录下指定后缀的文件名

package com.heima.test;

import java.io.File;

public class Test3 {

    /**
     ** 需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称
     */
    public static void main(String[] args) {
        File dir = new File("C:/Users/yang/Desktop");
        String[] arr = dir.list();              //获取e盘下所有的文件或文件夹
        for (String string : arr) {
            if(string.endsWith(".jpg")) {
                System.out.println(string);
            }
        }
        File[] subFiles = dir.listFiles();      //获取e盘下所有的文件或文件夹对象
        for (File file : subFiles) {
            if(file.isFile() && file.getName().endsWith(".jpg")) {
                System.out.println(file);
            }
        }
        
    }

}

文件名称过滤器的概述及使用

  • A:文件名称过滤器的概述
    • public String[] list(FilenameFilter filter)
    • public File[] listFiles(FileFilter filter)
  • B:文件名称过滤器的使用
    • 需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称
  • C:源码分析
    • 带文件名称过滤器的list()方法的源码
package com.heima.test;

import java.io.File;
import java.io.FilenameFilter;

public class Test3 {

    /**
     ** 需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称
     */
    public static void main(String[] args) {
        File dir = new File("C:/Users/yang/Desktop");
            
        String[] arr1 = dir.list(new FilenameFilter(){

            @Override
            public boolean accept(File dir, String name) {
                //System.out.println(dir);
                //System.out.println(name);
                File file = new File(dir, name);
                return file.isFile() && file.getName().endsWith(".jpg");
            }
        });
        
        for (String string : arr1) {
            System.out.println(string);
        }
    }

}

IO流概述及其分类

  • 1.概念
    • IO流用来处理设备之间的数据传输
    • Java对数据的操作是通过流的方式
    • Java用于操作流的类都在IO包中
    • 流按流向分为两种:输入流,输出流。
    • 流按操作类型分为两种:
      • 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
      • 字符流 : 字符流只能操作纯字符数据,比较方便。
  • 2.IO流常用父类
    • 字节流的抽象父类:
      • InputStream
      • OutputStream
    • 字符流的抽象父类:
      • Reader
      • Writer
  • 3.IO程序书写
    • 使用前,导入IO包中的类
    • 使用时,进行IO异常处理
    • 使用后,释放资源

FileInputStream

  • read()一次读取一个字节
package com.heima.stream;

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

public class Demo1_FileInputStream {

    /*
     */
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("xxx.txt");//创建一个文件输入流对象,并关联aaa.txt
        int b;
        while((b = fis.read()) != -1) {     //当文件读完输出为-1,所以设置-1为结束标志
            System.out.println(b);
        }
        
        fis.close();
    }

    public static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("xxx.txt");   //创建流对象
        int x = fis.read();         //从硬盘上读取一个字节
        System.out.println(x);
        int y = fis.read();         //从硬盘上读取一个字节
        System.out.println(y);
        int z = fis.read();         //从硬盘上读取一个字节
        System.out.println(z);
        int a = fis.read();         //从硬盘上读取一个字节
        System.out.println(a);
        int b = fis.read();         //从硬盘上读取一个字节
        System.out.println(b);
        
        fis.close();                //关流释放资源
    }

}

read()方法返回值为什么是int

  • read()方法读取的是一个字节,为什么返回是int,而不是byte
    因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111
    那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型

FileOutputStream以及FileOutputStream的追加

  • write()一次写出一个字节
package com.heima.stream;

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

public class Demo2_FileOutputStream {

    /**
     * FileOutputStream在创建对象的时候是如果没有这个文件会帮我创建出来
     * 如果有这个文件就会先将文件清空
     */
    public static void main(String[] args) throws IOException {
        //FileOutputStream fos = new FileOutputStream("yyy.txt");       //创建IO字节输出流对象,如果没有就自动创建一个
        FileOutputStream fos = new FileOutputStream("yyy.txt",true);    //如果想续写,就在第二个参数传true    
        fos.write(97);      //虽然写出的是一个int数,但是到文件上的是一个字节,会自动去除前3个8位
        fos.write(98);
        fos.write(99);
            
        fos.close();
    }

}

拷贝图片

由于是一个字节一个字节的读,所以效率很低。

package com.heima.stream;

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

public class Demo3_Copy {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("Math.jpg");  //创建输入流对象,关联Math.jpg
        FileOutputStream fos = new FileOutputStream("copy.jpg");    //创建输出流对象,关联copy.jpg
        
        int b;
        while((b = fis.read()) != -1) {     //在不断的读取每一个字节
            fos.write(b);                   //将每一个字节写出
        }
        
        fis.close();                        //关流释放资源
        fos.close();
    }

}

相关文章

  • ##Java学习笔记之基础类库笔记

    Java学习笔记之基础类库笔记 Object 所有类,数组,枚举类的父类 Objects(Java7新增) 工具类...

  • Java学习笔记7

    TreeSet保证元素唯一和自然排序的原理和图解 TreeSet保证元素唯一和比较器排序的原理及代码实现 Tree...

  • Java学习笔记7

    JDBC JDBC的全称为:Java Database Connectivity,即java数据库连接。 使用JD...

  • nio

    参考文章 Java Nio Java NIO学习笔记 - NIO客户端时序图 Java NIO学习笔记 - NIO...

  • Java 学习笔记(13)——lambda 表达式

    title: Java 学习笔记(11)——lambda 表达式tags: [Java 基础, 学习笔记, 函数式...

  • java io

    参考Java IO学习笔记(一):File类Java IO学习笔记(二):RandomAccessFile类Jav...

  • 文章目录

    Markdown学习 Markdown学习 Java学习 Servlet学习笔记 Java问题 Tomcat问题修...

  • Java编程思想学习笔记(7)

    Java编程思想学习笔记(7) 复用类 复用代码是Java的功能之一。 Java中对代码的复用是围绕着类展开的,可...

  • Java学习日记

    title: Java学习笔记date: 2018-05-18 12:00:00tags: Java 学习笔记 P...

  • Java NIO 学习笔记(三)----Selector

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔...

网友评论

      本文标题:Java学习笔记7

      本文链接:https://www.haomeiwen.com/subject/rcwbxqtx.html