美文网首页
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学习笔记7

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