JavaSE基础知识是附上代码实现2

###13.01_常见对象(StringBuffer类的概述)
* A:StringBuffer类概述
    * 通过JDK提供的API,查看StringBuffer类的说明
    * 线程安全的可变字符序列 
* B:StringBuffer和String的区别
    * String是一个不可变的字符序列
    * StringBuffer是一个可变的字符序列 

###13.02_常见对象(StringBuffer类的构造方法)
* A:StringBuffer的构造方法:
    * public StringBuffer():无参构造方法
    * public StringBuffer(int capacity):指定容量的字符串缓冲区对象
    * public StringBuffer(String str):指定字符串内容的字符串缓冲区对象
* B:StringBuffer的方法:
    * public int capacity():返回当前容量。    理论值(不掌握)
    * public int length():返回长度(字符数)。 实际值
* C:案例演示
    * 构造方法和长度方法的使用

###13.03_常见对象(StringBuffer的添加功能)
* A:StringBuffer的添加功能
    * public StringBuffer append(String str):
        * 可以把任意类型数据添加到字符串缓冲区里面,并返回字符串缓冲区本身
    * public StringBuffer insert(int offset,String str):
        * 在指定位置把任意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身

###13.04_常见对象(StringBuffer的删除功能)
* A:StringBuffer的删除功能
    * public StringBuffer deleteCharAt(int index):
        * 删除指定位置的字符,并返回本身
    * public StringBuffer delete(int start,int end):
        * 删除从指定位置开始指定位置结束的内容,并返回本身

###13.05_常见对象(StringBuffer的替换和反转功能)
* A:StringBuffer的替换功能
    * public StringBuffer replace(int start,int end,String str):
        * 从start开始到end用str替换
* B:StringBuffer的反转功能
    * public StringBuffer reverse():
        * 字符串反转

###13.06_常见对象(StringBuffer的截取功能及注意事项)
* A:StringBuffer的截取功能
    * public String substring(int start):
        * 从指定位置截取到末尾
    * public String substring(int start,int end):
        * 截取从指定位置开始到结束位置,包括开始位置,不包括结束位置
* B:注意事项
    * 注意:返回值类型不再是StringBuffer本身

###13.07_常见对象(StringBuffer和String的相互转换)
* A:String -- StringBuffer
    * a:通过构造方法
    * b:通过append()方法
* B:StringBuffer -- String
    * a:通过构造方法
    * b:通过toString()方法
    * c:通过subString(0,length);

###13.08_常见对象(把数组转成字符串)
* A:案例演示
    * 需求:把数组中的数据按照指定个格式拼接成一个字符串
    * 
            举例:
                int[] arr = {1,2,3};    
            输出结果:
                "[1, 2, 3]"
                
            用StringBuffer的功能实现

###13.09_常见对象(字符串反转)
* A:案例演示

        需求:把字符串反转
            举例:键盘录入"abc"        
            输出结果:"cba"
            
        用StringBuffer的功能实现    

###13.10_常见对象(StringBuffer和StringBuilder的区别)
* A:StringBuilder的概述
    * 通过查看API了解一下StringBuilder类
* B:面试题
    * String,StringBuffer,StringBuilder的区别
    * StringBuffer和StringBuilder的区别
    * StringBuffer是jdk1.0版本的,是线程安全的,效率低
    * StringBuilder是jdk1.5版本的,是线程不安全的,效率高

    * String和StringBuffer,StringBuilder的区别
    * String是一个不可变的字符序列
    * StringBuffer,StringBuilder是可变的字符序列

###13.11_常见对象(String和StringBuffer分别作为参数传递)
* A:形式参数问题
    * String作为参数传递
    * StringBuffer作为参数传递 
* B:案例演示
    * String和StringBuffer分别作为参数传递问题

###13.12_常见对象(数组高级冒泡排序原理图解)
* A:画图演示

        需求:
            数组元素:{24, 69, 80, 57, 13}
            请对数组元素进行排序。
            
            冒泡排序
                相邻元素两两比较,大的往后放,第一次完毕,最大值出现在了最大索引处


###13.13_常见对象(数组高级冒泡排序代码实现)
* A:案例演示
    * 数组高级冒泡排序代码

###13.14_常见对象(数组高级选择排序原理图解)
* A:画图演示
    * 需求:
        * 数组元素:{24, 69, 80, 57, 13}
        * 请对数组元素进行排序。
        
        * 选择排序
            * 从0索引开始,依次和后面元素比较,小的往前放,第一次完毕,最小值出现在了最小索引处


###13.15_常见对象(数组高级选择排序代码实现)
* A:案例演示
    * 数组高级选择排序代码

###13.16_常见对象(数组高级二分查找原理图解)
* A:画图演示
    * 二分查找  
    * 前提:数组元素有序

###13.17_常见对象(数组高级二分查找代码实现及注意事项)
* A:案例演示
    * 数组高级二分查找代码
* B:注意事项
    * 如果数组无序,就不能使用二分查找。
        * 因为如果你排序了,但是你排序的时候已经改变了我最原始的元素索引。

###13.18_常见对象(Arrays类的概述和方法使用)
* A:Arrays类概述
    * 针对数组进行操作的工具类。
    * 提供了排序,查找等功能。
* B:成员方法
    * public static String toString(int[] a)
    * public static void sort(int[] a)
    * public static int binarySearch(int[] a,int key)

###13.19_常见对象(基本类型包装类的概述)
* A:为什么会有基本类型包装类
    * 将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据。
* B:常用操作
    * 常用的操作之一:用于基本数据类型与字符串之间的转换。
* C:基本类型和包装类的对应

        byte             Byte
        short            Short
        int                Integer
        long            Long
        float            Float
        double            Double
        char            Character
        boolean            Boolean

###13.20_常见对象(Integer类的概述和构造方法)
* A:Integer类概述
    * 通过JDK提供的API,查看Integer类的说明

    * Integer 类在对象中包装了一个基本类型 int 的值,
    * 该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,
    * 还提供了处理 int 类型时非常有用的其他一些常量和方法
* B:构造方法
    * public Integer(int value)
    * public Integer(String s)
* C:案例演示
    * 使用构造方法创建对象

###13.21_常见对象(String和int类型的相互转换)
* A:int -- String
    * a:和""进行拼接
    * b:public static String valueOf(int i)
    * c:int -- Integer -- String(Integer类的toString方法())
    * d:public static String toString(int i)(Integer类的静态方法)
* B:String -- int
    * a:String -- Integer -- int
    * public static int parseInt(String s)

###13.22_常见对象(JDK5的新特性自动装箱和拆箱)
* A:JDK5的新特性
    * 自动装箱:把基本类型转换为包装类类型
    * 自动拆箱:把包装类类型转换为基本类型
* B:案例演示
    * JDK5的新特性自动装箱和拆箱
    
    * Integer ii = 100;
    * ii += 200;
* C:注意事项
    * 在使用时,Integer  x = null;代码就会出现NullPointerException。
    * 建议先判断是否为null,然后再使用。

###13.23_常见对象(Integer的面试题)
* A:Integer的面试题

        看程序写结果
        
        Integer i1 = new Integer(97);
        Integer i2 = new Integer(97);
        System.out.println(i1 == i2);
        System.out.println(i1.equals(i2));
        System.out.println("-----------");
    
        Integer i3 = new Integer(197);
        Integer i4 = new Integer(197);
        System.out.println(i3 == i4);
        System.out.println(i3.equals(i4));
        System.out.println("-----------");
    
        Integer i5 = 97;
        Integer i6 = 97;
        System.out.println(i5 == i6);
        System.out.println(i5.equals(i6));
        System.out.println("-----------");
    
        Integer i7 = 197;
        Integer i8 = 197;
        System.out.println(i7 == i8);
        System.out.println(i7.equals(i8));

###13.24_day13总结
* 把今天的知识点总结一遍。

###14.01_常见对象(正则表达式的概述和简单使用)
* A:正则表达式
    * 是指一个用来描述或者匹配一系列符合某个语法规则的字符串的单个字符串。其实就是一种规则。有自己特殊的应用。
    * 作用:比如注册邮箱,邮箱有用户名和密码,一般会对其限制长度,这个限制长度的事情就是正则表达式做的
* B:案例演示
    * 需求:校验qq号码.
        * 1:要求必须是5-15位数字
        * 2:0不能开头
        * 3:必须都是数字
        
    * a:非正则表达式实现
    * b:正则表达式实现

###14.02_常见对象(字符类演示)
* A:字符类
    * [abc] a、b 或 c(简单类) 
    * [^abc] 任何字符,除了 a、b 或 c(否定) 
    * [a-zA-Z] a到 z 或 A到 Z,两头的字母包括在内(范围) 
    * [0-9] 0到9的字符都包括
###14.03_常见对象(预定义字符类演示)
* A:预定义字符类
    * . 任何字符。
    * \d 数字:[0-9]
    * \w 单词字符:[a-zA-Z_0-9]
###14.04_常见对象(数量词)
* A:Greedy 数量词 
    * X? X,一次或一次也没有
    * X* X,零次或多次
    * X+ X,一次或多次
    * X{n} X,恰好 n 次 
    * X{n,} X,至少 n 次 
    * X{n,m} X,至少 n 次,但是不超过 m 次 

###14.05_常见对象(正则表达式的分割功能)
* A:正则表达式的分割功能
    * String类的功能:public String[] split(String regex)
* B:案例演示
    * 正则表达式的分割功能

###14.06_常见对象(把给定字符串中的数字排序)
* A:案例演示
    * 需求:我有如下一个字符串:”91 27 46 38 50”,请写代码实现最终输出结果是:”27 38 46 50 91”

###14.07_常见对象(正则表达式的替换功能)
* A:正则表达式的替换功能
    * String类的功能:public String replaceAll(String regex,String replacement)
* B:案例演示
    * 正则表达式的替换功能

###14.08_常见对象(正则表达式的分组功能)
* A:正则表达式的分组功能
    * 捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组: 

        1     ((A)(B(C))) 
        2     (A 
        3     (B(C)) 
        4     (C) 
    
        组零始终代表整个表达式。
B:案例演示
    a:切割
        需求:请按照叠词切割: "sdqqfgkkkhjppppkl";
    b:替换
        需求:我我....我...我.要...要要...要学....学学..学.编..编编.编.程.程.程..程
        将字符串还原成:“我要学编程”。
###14.09_常见对象(Pattern和Matcher的概述)
* A:Pattern和Matcher的概述
* B:模式和匹配器的典型调用顺序
    * 通过JDK提供的API,查看Pattern类的说明

    * 典型的调用顺序是 
    * Pattern p = Pattern.compile("a*b");
    * Matcher m = p.matcher("aaaaab");
    * boolean b = m.matches();

###14.10_常见对象(正则表达式的获取功能)
* A:正则表达式的获取功能
    * Pattern和Matcher的结合使用
* B:案例演示
    * 需求:把一个字符串中的手机号码获取出来


###14.11_常见对象(Math类概述和方法使用)
* A:Math类概述
    * Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。 
* B:成员方法
    * public static int abs(int a)
    * public static double ceil(double a)
    * public static double floor(double a)
    * public static int max(int a,int b) min自学
    * public static double pow(double a,double b)
    * public static double random()
    * public static int round(float a) 参数为double的自学
    * public static double sqrt(double a)

###14.12_常见对象(Random类的概述和方法使用)
* A:Random类的概述
    * 此类用于产生随机数如果用相同的种子创建两个 Random 实例,
    * 则对每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。
* B:构造方法
    * public Random()
    * public Random(long seed)
* C:成员方法
    * public int nextInt()
    * public int nextInt(int n)(重点掌握)

###14.13_常见对象(System类的概述和方法使用)
* A:System类的概述
    * System 类包含一些有用的类字段和方法。它不能被实例化。 
* B:成员方法
    * public static void gc()
    * public static void exit(int status)
    * public static long currentTimeMillis()
    * pubiic static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 
* C:案例演示
    * System类的成员方法使用

###14.14_常见对象(BigInteger类的概述和方法使用)
* A:BigInteger的概述
    * 可以让超过Integer范围内的数据进行运算
* B:构造方法
    * public BigInteger(String val)
* C:成员方法
    * public BigInteger add(BigInteger val)
    * public BigInteger subtract(BigInteger val)
    * public BigInteger multiply(BigInteger val)
    * public BigInteger divide(BigInteger val)
    * public BigInteger[] divideAndRemainder(BigInteger val)

###14.15_常见对象(BigDecimal类的概述和方法使用)
* A:BigDecimal的概述
    * 由于在运算的时候,float类型和double很容易丢失精度,演示案例。
    * 所以,为了能精确的表示、计算浮点数,Java提供了BigDecimal

    * 不可变的、任意精度的有符号十进制数。
* B:构造方法
    * public BigDecimal(String val)
* C:成员方法
    * public BigDecimal add(BigDecimal augend)
    * public BigDecimal subtract(BigDecimal subtrahend)
    * public BigDecimal multiply(BigDecimal multiplicand)
    * public BigDecimal divide(BigDecimal divisor)
* D:案例演示
    * BigDecimal类的构造方法和成员方法使用

###14.16_常见对象(Date类的概述和方法使用)(掌握)
* A:Date类的概述
    * 类 Date 表示特定的瞬间,精确到毫秒。 
* B:构造方法
    * public Date()
    * public Date(long date)
* C:成员方法
    * public long getTime()
    * public void setTime(long time)

###14.17_常见对象(SimpleDateFormat类实现日期和字符串的相互转换)(掌握)
* A:DateFormat类的概述
    * DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。是抽象类,所以使用其子类SimpleDateFormat
* B:SimpleDateFormat构造方法
    * public SimpleDateFormat()
    * public SimpleDateFormat(String pattern)
* C:成员方法
    * public final String format(Date date)
    * public Date parse(String source)


###14.18_常见对象(你来到这个世界多少天案例)(掌握)
* A:案例演示
    * 需求:算一下你来到这个世界多少天?

###14.19_常见对象(Calendar类的概述和获取日期的方法)(掌握)
* A:Calendar类的概述
    * Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。
* B:成员方法
    * public static Calendar getInstance()
    * public int get(int field)


###14.20_常见对象(Calendar类的add()和set()方法)(掌握)
* A:成员方法
    * public void add(int field,int amount)
    * public final void set(int year,int month,int date)
* B:案例演示
    * Calendar类的成员方法使用

###14.21_常见对象(如何获取任意年份是平年还是闰年)(掌握)
* A:案例演示
    * 需求:键盘录入任意一个年份,判断该年是闰年还是平年

###14.22_day14总结
* 把今天的知识点总结一遍。

###15.01_集合框架(对象数组的概述和使用)
* A:案例演示
    * 需求:我有5个学生,请把这个5个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。

        Student[] arr = new Student[5];                    //存储学生对象
        arr[0] = new Student("张三", 23);
        arr[1] = new Student("李四", 24);
        arr[2] = new Student("王五", 25);
        arr[3] = new Student("赵六", 26);
        arr[4] = new Student("马哥", 20);
        
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        
* B:画图演示
    * 把学生数组的案例画图讲解
    * 数组和集合存储引用数据类型,存的都是地址值

###15.02_集合框架(集合的由来及集合继承体系图)
* A:集合的由来
    * 数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少 
* B:数组和集合的区别
    * 区别1 : 
        * 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
        * 集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象
    * 区别2:
        * 数组长度是固定的,不能自动增长
        * 集合的长度的是可变的,可以根据元素的增加而增长
* C:数组和集合什么时候用
        * 1,如果元素个数是固定的推荐用数组
        * 2,如果元素个数不是固定的推荐用集合
* D:集合继承体系图

###15.03_集合框架(Collection集合的基本功能测试)
* A:案例演示    

        基本功能演示
        
        boolean add(E e)
        boolean remove(Object o)
        void clear()
        boolean contains(Object o)
        boolean isEmpty()
        int size()

* B:注意:

        collectionXxx.java使用了未经检查或不安全的操作.
        注意:要了解详细信息,请使用 -Xlint:unchecked重新编译.
        java编译器认为该程序存在安全隐患
        温馨提示:这不是编译失败,所以先不用理会,等学了泛型你就知道了
      
###15.04_集合框架(集合的遍历之集合转数组遍历)
* A:集合的遍历
    * 其实就是依次获取集合中的每一个元素。
* B:案例演示
    * 把集合转成数组,可以实现集合的遍历
    * toArray()
    *
        
            Collection coll = new ArrayList();
            coll.add(new Student("张三",23));        //Object obj = new Student("张三",23);
            coll.add(new Student("李四",24));
            coll.add(new Student("王五",25));
            coll.add(new Student("赵六",26));
            
            Object[] arr = coll.toArray();                //将集合转换成数组
            for (int i = 0; i < arr.length; i++) {
                Student s = (Student)arr[i];            //强转成Student
                System.out.println(s.getName() + "," + s.getAge());
            }

###15.05_集合框架(Collection集合的带All功能测试)
* A:案例演示

        带All的功能演示
        
        boolean addAll(Collection c)
        boolean removeAll(Collection c)
        boolean containsAll(Collection c)
        boolean retainAll(Collection c)


###15.06_集合框架(集合的遍历之迭代器遍历)
* A:迭代器概述
    * 集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历) 
* B:案例演示
    * 迭代器的使用
        
            Collection c = new ArrayList();
            c.add("a");
            c.add("b");
            c.add("c");
            c.add("d");
            
            Iterator it = c.iterator();                        //获取迭代器的引用
            while(it.hasNext()) {                            //集合中的迭代方法(遍历)
                System.out.println(it.next());
            }
    
            
###15.07_集合框架(Collection存储自定义对象并遍历)
* A:案例演示
    * Collection存储自定义对象并用迭代器遍历
    * 
            Collection c = new ArrayList();
            
            c.add(new Student("张三",23));
            c.add(new Student("李四",24));
            c.add(new Student("王五",25));
            c.add(new Student("赵六",26));
            c.add(new Student("赵六",26));
            
            for(Iterator it = c.iterator();it.hasNext();) {
                Student s = (Student)it.next();                        //向下转型
                System.out.println(s.getName() + "," + s.getAge());    //获取对象中的姓名和年龄
            }
            System.out.println("------------------------------");
            Iterator it = c.iterator();                                //获取迭代器
            while(it.hasNext()) {                                    //判断集合中是否有元素
                //System.out.println(((Student)(it.next())).getName() + "," + ((Student)(it.next())).getAge());
                Student s = (Student)it.next();                        //向下转型
                System.out.println(s.getName() + "," + s.getAge());    //获取对象中的姓名和年龄
            }
        

###15.08_集合框架(迭代器的原理及源码解析)(了解)
* A:迭代器原理
    * 迭代器原理:迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样,那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的,但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取出接口,然后在每个类的内部,定义自己迭代方式,这样做的好处有二,第一规定了整个集合体系的遍历方式都是hasNext()和next()方法,第二,代码有底层内部实现,使用者不用管怎么实现的,会用即可 
* B:迭代器源码解析
    * 1,在eclipse中ctrl + shift + t找到ArrayList类
    * 2,ctrl+o查找iterator()方法
    * 3,查看返回值类型是new Itr(),说明Itr这个类实现Iterator接口
    * 4,查找Itr这个内部类,发现重写了Iterator中的所有抽象方法 

###15.09_集合框架(List集合的特有功能概述和测试)
* A:List集合的特有功能概述
    * void add(int index,E element)
    * E remove(int index)
    * E get(int index)
    * E set(int index,E element)

###15.10_集合框架(List集合存储学生对象并遍历)
* A:案例演示
    * 通过size()和get()方法结合使用遍历。

            List list = new ArrayList();
            list.add(new Student("张三", 18));
            list.add(new Student("李四", 18));
            list.add(new Student("王五", 18));
            list.add(new Student("赵六", 18));
            
            for(int i = 0; i < list.size(); i++) {
                Student s = (Student)list.get(i);
                System.out.println(s.getName() + "," + s.getAge());
            }

###15.11_集合框架(并发修改异常产生的原因及解决方案)
* A:案例演示
    * 需求:我有一个集合,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。

            List list = new ArrayList();
            list.add("a");
            list.add("b");
            list.add("world");
            list.add("d");
            list.add("e");
            
            /*Iterator it = list.iterator();
            while(it.hasNext()) {
                String str = (String)it.next();
                if(str.equals("world")) {
                    list.add("javaee");            //这里会抛出ConcurrentModificationException并发修改异常
                }
            }*/
            
            
* B:ConcurrentModificationException出现
    * 迭代器遍历,集合修改集合
* C:解决方案
    * a:迭代器迭代元素,迭代器修改元素(ListIterator的特有功能add)
    * b:集合遍历元素,集合修改元素

            ListIterator lit = list.listIterator();        //如果想在遍历的过程中添加元素,可以用ListIterator中的add方法
            while(lit.hasNext()) {
                String str = (String)lit.next();
                if(str.equals("world")) {
                    lit.add("javaee");    
                    //list.add("javaee");
                }
            }

###15.12_集合框架(ListIterator)(了解)
* boolean hasNext()是否有下一个
* boolean hasPrevious()是否有前一个
* Object next()返回下一个元素
* Object previous();返回上一个元素

###15.13_集合框架(Vector的特有功能)
* A:Vector类概述
* B:Vector类特有功能
    * public void addElement(E obj)
    * public E elementAt(int index)
    * public Enumeration elements()
* C:案例演示    
    * Vector的迭代

            Vector v = new Vector();                //创建集合对象,List的子类
            v.addElement("a");
            v.addElement("b");
            v.addElement("c");
            v.addElement("d");
            
            //Vector迭代
            Enumeration en = v.elements();            //获取枚举
            while(en.hasMoreElements()) {            //判断集合中是否有元素
                System.out.println(en.nextElement());//获取集合中的元素
            }

###15.14_集合框架(数据结构之数组和链表)
* A:数组
    * 查询快修改也快
    * 增删慢
* B:链表
    * 查询慢,修改也慢
    * 增删快

###15.15_集合框架(List的三个子类的特点)
* A:List的三个子类的特点

        ArrayList:
            底层数据结构是数组,查询快,增删慢。
            线程不安全,效率高。
        Vector:
            底层数据结构是数组,查询快,增删慢。
            线程安全,效率低。
        Vector相对ArrayList查询慢(线程安全的)
        Vector相对LinkedList增删慢(数组结构)
        LinkedList:
            底层数据结构是链表,查询慢,增删快。
            线程不安全,效率高。

        Vector和ArrayList的区别
            Vector是线程安全的,效率低
            ArrayList是线程不安全的,效率高
        共同点:都是数组实现的
        ArrayList和LinkedList的区别
            ArrayList底层是数组结果,查询和修改快
            LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
        共同点:都是线程不安全的
* B:List有三个儿子,我们到底使用谁呢?
        查询多用ArrayList
        增删多用LinkedList
        如果都多ArrayList
###15.16_day15总结
把今天的知识点总结一遍。

###16.01_集合框架(去除ArrayList中重复字符串元素方式)(掌握)
* A:案例演示
    * 需求:ArrayList去除集合中字符串的重复值(字符串的内容相同)
    * 思路:创建新集合方式

            /**
             *  A:案例演示
             * 需求:ArrayList去除集合中字符串的重复值(字符串的内容相同)
             * 思路:创建新集合方式
             */
            public static void main(String[] args) {
                ArrayList list = new ArrayList();
                list.add("a");
                list.add("a");
                list.add("b");
                list.add("b");
                list.add("b");
                list.add("c");
                list.add("c");
                list.add("c");
                list.add("c");
                
                System.out.println(list);
                ArrayList newList = getSingle(list);
                System.out.println(newList);
            }
        
            /*
             * 去除重复
             * 1,返回ArrayList
             * 2,参数列表ArrayList
             */
            public static ArrayList getSingle(ArrayList list) {
                ArrayList newList = new ArrayList();            //创建一个新集合
                Iterator it = list.iterator();                    //获取迭代器
                while(it.hasNext()) {                            //判断老集合中是否有元素
                    String temp = (String)it.next();            //将每一个元素临时记录住
                    if(!newList.contains(temp)) {                //如果新集合中不包含该元素
                        newList.add(temp);                        //将该元素添加到新集合中
                    }
                }
                return newList;                                    //将新集合返回
            }
###16.02_集合框架(去除ArrayList中重复自定义对象元素)(掌握)
* A:案例演示
    * 需求:ArrayList去除集合中自定义对象元素的重复值(对象的成员变量值相同)
* B:注意事项
    * 重写equals()方法的

###16.03_集合框架(LinkedList的特有功能)(掌握)
* A:LinkedList类概述
* B:LinkedList类特有功能
    * public void addFirst(E e)及addLast(E e)
    * public E getFirst()及getLast()
    * public E removeFirst()及public E removeLast()
    * public E get(int index);

###16.04_集合框架(栈和队列数据结构)(掌握)
* 栈
    * 先进后出 
* 队列
    * 先进先出

###16.05_集合框架(用LinkedList模拟栈数据结构的集合并测试)(掌握)
* A:案例演示
    * 需求:请用LinkedList模拟栈数据结构的集合,并测试
    * 创建一个类将Linked中的方法封装
    * 
            public class Stack {
                private LinkedList list = new LinkedList();        //创建LinkedList对象
                
                public void in(Object obj) {
                    list.addLast(obj);                            //封装addLast()方法
                }
                
                public Object out() {
                    return list.removeLast();                    //封装removeLast()方法
                }
                
                public boolean isEmpty() {
                    return list.isEmpty();                        //封装isEmpty()方法
                }
            }
    

###16.06_集合框架(泛型概述和基本使用)(掌握)
* A:泛型概述
* B:泛型好处
    * 提高安全性(将运行期的错误转换到编译期) 
    * 省去强转的麻烦
* C:泛型基本使用
    * <>中放的必须是引用数据类型 
* D:泛型使用注意事项
    * 前后的泛型必须一致,或者后面的泛型可以省略不写(1.7的新特性菱形泛型)  

###16.07_集合框架(ArrayList存储字符串和自定义对象并遍历泛型版)(掌握)
* A:案例演示
    * ArrayList存储字符串并遍历泛型版

###16.08_集合框架(泛型的由来)(了解)
* A:案例演示
    * 泛型的由来:通过Object转型问题引入
    * 早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。

###16.09_集合框架(泛型类的概述及使用)(了解)
* A:泛型类概述
    * 把泛型定义在类上
* B:定义格式
    * public class 类名<泛型类型1,…>
* C:注意事项    
    * 泛型类型必须是引用类型
* D:案例演示
    * 泛型类的使用

###16.10_集合框架(泛型方法的概述和使用)(了解)
* A:泛型方法概述
    * 把泛型定义在方法上
* B:定义格式    
    * public <泛型类型> 返回类型 方法名(泛型类型 变量名)
* C:案例演示
    * 泛型方法的使用

###16.11_集合框架(泛型接口的概述和使用)(了解)
* A:泛型接口概述
    * 把泛型定义在接口上
* B:定义格式    
    * public interface 接口名<泛型类型>
* C:案例演示
    * 泛型接口的使用

###16.12_集合框架(泛型高级之通配符)(了解)
* A:泛型通配符
    * 任意类型,如果没有明确,那么就是Object以及任意的Java类了
* B:? extends E
    * 向下限定,E及其子类
* C:? super E
    * 向上限定,E及其父类


###16.13_集合框架(增强for的概述和使用)(掌握)
* A:增强for概述
    * 简化数组和Collection集合的遍历
* B:格式:

        for(元素数据类型 变量 : 数组或者Collection集合) {
            使用变量即可,该变量就是元素
        }
* C:案例演示
    * 数组,集合存储元素用增强for遍历
* D:好处
    * 简化遍历


###16.14_集合框架(ArrayList存储字符串和自定义对象并遍历增强for版)(掌握)
* A:案例演示
    * ArrayList存储字符串并遍历增强for版
    * 
            ArrayList list = new ArrayList<>();
            list.add("a");
            list.add("b");
            list.add("c");
            list.add("d");
            
            for(String s : list) {
                System.out.println(s);
            }
###16.15_集合框架(三种迭代的能否删除)(掌握)
* 普通for循环,可以删除,但是索引要--
* 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常
* 增强for循环不能删除

###16.16_集合框架(静态导入的概述和使用)(掌握)
* A:静态导入概述
* B:格式:
    * import static 包名….类名.方法名;
    * 可以直接导入到方法的级别
* C:注意事项
    * 方法必须是静态的,如果有多个同名的静态方法,容易不知道使用谁?这个时候要使用,必须加前缀。由此可见,意义不大,所以一般不用,但是要能看懂。

###16.17_集合框架(可变参数的概述和使用)(掌握)
* A:可变参数概述
    * 定义方法的时候不知道该定义多少个参数
* B:格式
    * 修饰符 返回值类型 方法名(数据类型…  变量名){}
* C:注意事项:
    * 这里的变量其实是一个数组
    * 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个

###16.18_集合框架(Arrays工具类的asList()方法的使用)(掌握)
* A:案例演示
    * Arrays工具类的asList()方法的使用
    * Collection中toArray(T[] a)泛型版的集合转数组

###16.19_集合框架(集合嵌套之ArrayList嵌套ArrayList)(掌握)
* A:案例演示
    * 集合嵌套之ArrayList嵌套ArrayList

###16.20_day16总结
* 把今天的知识点总结一遍。

###17.01_集合框架(HashSet存储字符串并遍历)
* A:Set集合概述及特点
    * 通过API查看即可
* B:案例演示
    * HashSet存储字符串并遍历
    * 
             HashSet hs = new HashSet<>();
            boolean b1 = hs.add("a");
            boolean b2 = hs.add("a");            //当存储不成功的时候,返回false
            
            System.out.println(b1);
            System.out.println(b2);
            for(String s : hs) {
                System.out.println(s);
            }

###17.02_集合框架(HashSet存储自定义对象保证元素唯一性)
* A:案例演示
    * 存储自定义对象,并保证元素唯一性。

            HashSet hs = new HashSet<>();
            hs.add(new Person("张三", 23));
            hs.add(new Person("张三", 23));
            hs.add(new Person("李四", 23));
            hs.add(new Person("李四", 23));
            hs.add(new Person("王五", 23));
            hs.add(new Person("赵六", 23));
* 重写hashCode()和equals()方法
###17.03_集合框架(HashSet存储自定义对象保证元素唯一性图解及代码优化)
* A:画图演示
    * 画图说明比较过程
* B:代码优化
    * 为了减少比较,优化hashCode()代码写法。
    * 最终版就是自动生成即可。

###17.04_集合框架(HashSet如何保证元素唯一性的原理)
* 1.HashSet原理
    * 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
    * 当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
        * 如果没有哈希值相同的对象就直接存入集合
        * 如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
* 2.将自定义类的对象存入HashSet去重复
    * 类中必须重写hashCode()和equals()方法
    * hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
    * equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储

###17.05_集合框架(LinkedHashSet的概述和使用)
* A:LinkedHashSet的特点
* B:案例演示
    * LinkedHashSet的特点
        * 可以保证怎么存就怎么取 

###17.06_集合框架(产生10个1-20之间的随机数要求随机数不能重复)
* A:案例演示
    * 需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复。并把最终的随机数输出到控制台。
    * 
            HashSet hs = new HashSet<>();        //创建集合对象
            Random r = new Random();                    //创建随机数对象
            
            while(hs.size() < 10) {
                int num = r.nextInt(20) + 1;            //生成1到20的随机数
                hs.add(num);
            }
            
            for (Integer integer : hs) {                //遍历集合
                System.out.println(integer);            //打印每一个元素
            }

###17.07_集合框架(练习)
* 使用Scanner从键盘读取一行输入,去掉其中重复字符, 打印出不同的那些字符
    * aaaabbbcccddd

            Scanner sc = new Scanner(System.in);            //创建键盘录入对象
            System.out.println("请输入一行字符串:");
            String line = sc.nextLine();                    //将键盘录入的字符串存储在line中
            char[] arr = line.toCharArray();                //将字符串转换成字符数组
            HashSet hs = new HashSet<>();        //创建HashSet集合对象
            
            for(char c : arr) {                                //遍历字符数组
                hs.add(c);                                    //将字符数组中的字符添加到集合中
            }
            
            for (Character ch : hs) {                        //遍历集合
                System.out.println(ch);
            }
###17.08_集合框架(练习)
* 将集合中的重复元素去掉

            public static void main(String[] args) {
                ArrayList list = new ArrayList<>();
                list.add("a");
                list.add("a");
                list.add("a");
                list.add("b");
                list.add("b");
                list.add("b");
                list.add("b");
                list.add("c");
                list.add("c");
                list.add("c");
                list.add("c");
                
                System.out.println(list);
                System.out.println("去除重复后:");
                getSingle(list);
                System.out.println(list);
            }
            
            /*
             * 将集合中的重复元素去掉
             * 1,void
             * 2,List list
             */
            
            public static void getSingle(List list) {
                LinkedHashSet lhs = new LinkedHashSet<>();
                lhs.addAll(list);                                    //将list集合中的所有元素添加到lhs
                list.clear();                                        //清空原集合
                list.addAll(lhs);                                    //将去除重复的元素添回到list中
            }

###17.09_集合框架(TreeSet存储Integer类型的元素并遍历)
* A:案例演示
    * TreeSet存储Integer类型的元素并遍历

###17.10_集合框架(TreeSet存储自定义对象)
* A:案例演示
    * 存储Person对象

###17.11_集合框架(TreeSet保证元素唯一和自然排序的原理和图解)
* A:画图演示
    * TreeSet保证元素唯一和自然排序的原理和图解

###17.12_集合框架(TreeSet存储自定义对象并遍历练习1)
* A:案例演示
    * TreeSet存储自定义对象并遍历练习1(按照姓名排序)

###17.13_集合框架(TreeSet存储自定义对象并遍历练习2)
* A:案例演示
    * TreeSet存储自定义对象并遍历练习2(按照姓名的长度排序)

###17.14_集合框架(TreeSet保证元素唯一和比较器排序的原理及代码实现)
* A:案例演示
    * TreeSet保证元素唯一和比较器排序的原理及代码实现

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

###17.16_集合框架(练习)
* 在一个集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且还不能去除重复

            public static void main(String[] args) {
                ArrayList list = new ArrayList<>();
                list.add("ccc");
                list.add("ccc");
                list.add("aaa");
                list.add("aaa");
                list.add("bbb");
                list.add("ddd");
                list.add("ddd");
                
                sort(list);
                System.out.println(list);
            }
            
            /*
             * 对集合中的元素排序,并保留重复
             * 1,void
             * 2,List list
             */
            public static void sort(List list) {
                TreeSet ts = new TreeSet<>(new Comparator() {        //定义比较器(new Comparator(){}是Comparator的子类对象)
        
                    @Override
                    public int compare(String s1, String s2) {                        //重写compare方法
                        int num = s1.compareTo(s2);                                    //比较内容
                        return num == 0 ? 1 : num;                                    //如果内容一样返回一个不为0的数字即可
                    }
                });
                
                ts.addAll(list);                                                    //将list集合中的所有元素添加到ts中
                list.clear();                                                        //清空list
                list.addAll(ts);                                                    //将ts中排序并保留重复的结果在添加到list中
            }

###17.17_集合框架(练习)
* 从键盘接收一个字符串, 程序对其中所有字符进行排序,例如键盘输入: helloitcast程序打印:acehillostt

        Scanner sc = new Scanner(System.in);            //创建键盘录入对象
        System.out.println("请输入一行字符串:");
        String line = sc.nextLine();                    //将键盘录入的字符串存储在line中
        char[] arr = line.toCharArray();                //将字符串转换成字符数组
        TreeSet ts = new TreeSet<>(new Comparator() {

            @Override
            public int compare(Character c1, Character c2) {
                //int num = c1.compareTo(c2);
                int num = c1 - c2;                    //自动拆箱
                return num == 0 ? 1 : num;
            }
        });
        
        for(char c : arr) {
            ts.add(c);
        }
        
        for(Character ch : ts) {
            System.out.print(ch);
        }
###17.18_集合框架(练习)
* 程序启动后, 可以从键盘输入接收多个整数, 直到输入quit时结束输入. 把所有输入的整数倒序排列打印.
            Scanner sc = new Scanner(System.in);        //创建键盘录入对象
            System.out.println("请输入:");
            TreeSet ts = new TreeSet<>(new Comparator() {//将比较器传给TreeSet的构造方法
    
                @Override
                public int compare(Integer i1, Integer i2) {
                    //int num = i2 - i1;                    //自动拆箱
                    int num = i2.compareTo(i1);
                    return num == 0 ? 1 : num;
                }
            });
            
            while(true) {
                String line = sc.nextLine();            //将键盘录入的字符串存储在line中
                if("quit".equals(line))                    //如果字符串常量和变量比较,常量放前面,这样不会出现空指针异常,变量里面可能存储null
                    break;
                try {
                    int num = Integer.parseInt(line);        //将数字字符串转换成数字
                    ts.add(num);
                } catch (Exception e) {
                    System.out.println("您录入的数据有误,请输入一个整数");
                }
                
            }
            
            for (Integer i : ts) {                        //遍历TreeSet集合
                System.out.println(i);
            }
###17.19_集合框架(键盘录入学生信息按照总分排序后输出在控制台)
* A:案例演示
    * 需求:键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台。
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入5个学生成绩格式是:(姓名,语文成绩,数学成绩,英语成绩)");
            TreeSet ts = new TreeSet<>(new Comparator() {
                @Override
                public int compare(Student s1, Student s2) {
                    int num = s2.getSum() - s1.getSum();            //根据学生的总成绩降序排列
                    return num == 0 ? 1 : num;
                }
            });
            
            while(ts.size() < 5) {
                String line = sc.nextLine();
                try {
                    String[] arr = line.split(",");
                    int chinese = Integer.parseInt(arr[1]);                //转换语文成绩
                    int math = Integer.parseInt(arr[2]);                //转换数学成绩
                    int english = Integer.parseInt(arr[3]);                //转换英语成绩
                    ts.add(new Student(arr[0], chinese, math, english));
                } catch (Exception e) {
                    System.out.println("录入格式有误,输入5个学生成绩格式是:(姓名,语文成绩,数学成绩,英语成绩");
                }
                
            }
            
            System.out.println("排序后的学生成绩是:");
            for (Student s : ts) {
                System.out.println(s);
            }

###17.20_day17总结
* 1.List
    * a.普通for循环, 使用get()逐个获取
    * b.调用iterator()方法得到Iterator, 使用hasNext()和next()方法
    * c.增强for循环, 只要可以使用Iterator的类都可以用
    * d.Vector集合可以使用Enumeration的hasMoreElements()和nextElement()方法
* 2.Set
    * a.调用iterator()方法得到Iterator, 使用hasNext()和next()方法
    * b.增强for循环, 只要可以使用Iterator的类都可以用
* 3.普通for循环,迭代器,增强for循环是否可以在遍历的过程中删除 

###18.01_集合框架(Map集合概述和特点)
* A:Map接口概述
    * 查看API可以知道:
        * 将键映射到值的对象
        * 一个映射不能包含重复的键
        * 每个键最多只能映射到一个值
* B:Map接口和Collection接口的不同
    * Map是双列的,Collection是单列的
    * Map的键唯一,Collection的子体系Set是唯一的
    * Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
    
###18.02_集合框架(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> entrySet():
        * V get(Object key):根据键获取值
        * Set keySet():获取集合中所有键的集合
        * Collection values():获取集合中所有值的集合
    * e:长度功能
        * int size():返回集合中的键值对的个数


###18.03_集合框架(Map集合的遍历之键找值)
* A:键找值思路:
    * 获取所有键的集合
    * 遍历键的集合,获取到每一个键
    * 根据键找值
* B:案例演示
    * Map集合的遍历之键找值

            HashMap hm = new HashMap<>();
            hm.put("张三", 23);
            hm.put("李四", 24);
            hm.put("王五", 25);
            hm.put("赵六", 26);
            
            /*Set keySet = hm.keySet();            //获取集合中所有的键
            Iterator it = keySet.iterator();    //获取迭代器
            while(it.hasNext()) {                        //判断单列集合中是否有元素
                String key = it.next();                    //获取集合中的每一个元素,其实就是双列集合中的键
                Integer value = hm.get(key);            //根据键获取值
                System.out.println(key + "=" + value);    //打印键值对
            }*/
            
            for(String key : hm.keySet()) {                //增强for循环迭代双列集合第一种方式
                System.out.println(key + "=" + hm.get(key));
            }
    
###18.04_集合框架(Map集合的遍历之键值对对象找键和值)
* A:键值对对象找键和值思路:
    * 获取所有键值对对象的集合
    * 遍历键值对对象的集合,获取到每一个键值对对象
    * 根据键值对对象找键和值
* B:案例演示
    * Map集合的遍历之键值对对象找键和值
    
            HashMap hm = new HashMap<>();
            hm.put("张三", 23);
            hm.put("李四", 24);
            hm.put("王五", 25);
            hm.put("赵六", 26);
            /*Set> entrySet = hm.entrySet();    //获取所有的键值对象的集合
            Iterator> it = entrySet.iterator();//获取迭代器
            while(it.hasNext()) {
                Entry en = it.next();                //获取键值对对象
                String key = en.getKey();                                //根据键值对对象获取键
                Integer value = en.getValue();                            //根据键值对对象获取值
                System.out.println(key + "=" + value);
            }*/
            
            for(Entry en : hm.entrySet()) {
                System.out.println(en.getKey() + "=" + en.getValue());
            }
        
C:源码分析

###18.05_集合框架(HashMap集合键是Student值是String的案例)
* A:案例演示
    * HashMap集合键是Student值是String的案例

###18.06_集合框架(LinkedHashMap的概述和使用)
* A:案例演示
    * LinkedHashMap的特点
        * 底层是链表实现的可以保证怎么存就怎么取

###18.07_集合框架(TreeMap集合键是Student值是String的案例)
* A:案例演示
    * TreeMap集合键是Student值是String的案例

###18.08_集合框架(统计字符串中每个字符出现的次数)
* A:案例演示
    * 需求:统计字符串中每个字符出现的次数
            String str = "aaaabbbcccccccccc";
            char[] arr = str.toCharArray();                        //将字符串转换成字符数组
            HashMap hm = new HashMap<>();    //创建双列集合存储键和值
            
            for(char c : arr) {                                    //遍历字符数组
                /*if(!hm.containsKey(c)) {                        //如果不包含这个键
                    hm.put(c, 1);                                //就将键和值为1添加
                }else {                                            //如果包含这个键
                    hm.put(c, hm.get(c) + 1);                    //就将键和值再加1添加进来
                }
                
                //hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
                Integer i = !hm.containsKey(c) ? hm.put(c, 1) : hm.put(c, hm.get(c) + 1);
                        }
            
            for (Character key : hm.keySet()) {                    //遍历双列集合
                System.out.println(key + "=" + hm.get(key));
            }


###18.09_集合框架(集合嵌套之HashMap嵌套HashMap)
* A:案例演示
    * 集合嵌套之HashMap嵌套HashMap

###18.10_集合框架(HashMap和Hashtable的区别)
* A:面试题
    * HashMap和Hashtable的区别
        * Hashtable是JDK1.0版本出现的,是线程安全的,效率低,HashMap是JDK1.2版本出现的,是线程不安全的,效率高
        * Hashtable不可以存储null键和null值,HashMap可以存储null键和null值
* B:案例演示    
    * HashMap和Hashtable的区别

###18.11_集合框架(Collections工具类的概述和常见方法讲解)
* A:Collections类概述
    * 针对集合操作 的工具类
* B:Collections成员方法

        public static void sort(List list)
        public static int binarySearch(List list,T key)
        public static T max(Collection coll)
        public static void reverse(List list)
        public static void shuffle(List list)

###18.12_集合框架(模拟斗地主洗牌和发牌)
* A:案例演示
    * 模拟斗地主洗牌和发牌,牌没有排序

            //买一副扑克
            String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
            String[] color = {"方片","梅花","红桃","黑桃"};
            ArrayList poker = new ArrayList<>();
            
            for(String s1 : color) {
                for(String s2 : num) {
                    poker.add(s1.concat(s2));
                }
            }
            
            poker.add("小王");
            poker.add("大王");
            //洗牌
            Collections.shuffle(poker);
            //发牌
            ArrayList gaojin = new ArrayList<>();
            ArrayList longwu = new ArrayList<>();
            ArrayList me = new ArrayList<>();
            ArrayList 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 == 1) {
                    longwu.add(poker.get(i));
                }else {
                    me.add(poker.get(i));
                }
            }
            
            //看牌
            
            System.out.println(gaojin);
            System.out.println(longwu);
            System.out.println(me);
            System.out.println(dipai);

###18.13_集合框架(模拟斗地主洗牌和发牌并对牌进行排序的原理图解)
* A:画图演示
    * 画图说明排序原理

###18.14_集合框架(模拟斗地主洗牌和发牌并对牌进行排序的代码实现)
* A:案例演示
    * 模拟斗地主洗牌和发牌并对牌进行排序的代码实现

            //买一副牌
            String[] num = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
            String[] color = {"方片","梅花","红桃","黑桃"};
            HashMap hm = new HashMap<>();            //存储索引和扑克牌
            ArrayList list = new ArrayList<>();            //存储索引
            int index = 0;                                            //索引的开始值
            for(String s1 : num) {
                for(String s2 : color) {
                    hm.put(index, s2.concat(s1));                    //将索引和扑克牌添加到HashMap中
                    list.add(index);                                //将索引添加到ArrayList集合中
                    index++;
                }
            }
            hm.put(index, "小王");
            list.add(index);
            index++;
            hm.put(index, "大王");
            list.add(index);
            //洗牌
            Collections.shuffle(list);
            //发牌
            TreeSet gaojin = new TreeSet<>();
            TreeSet longwu = new TreeSet<>();
            TreeSet me = new TreeSet<>();
            TreeSet dipai = new TreeSet<>();
            
            for(int i = 0; i < list.size(); i++) {
                if(i >= list.size() - 3) {
                    dipai.add(list.get(i));                         //将list集合中的索引添加到TreeSet集合中会自动排序
                }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("高进", gaojin, hm);
            lookPoker("龙五", longwu, hm);
            lookPoker("冯佳", me, hm);
            lookPoker("底牌", dipai, hm);
            
        }
        
        public static void lookPoker(String name,TreeSet ts,HashMap hm) {
            System.out.print(name + "的牌是:");
            for (Integer index : ts) {
                System.out.print(hm.get(index) + " ");
            }
            
            System.out.println();
        }
###18.15_集合框架(泛型固定下边界)
* ? super E

###18.16_day18总结
* 把今天的知识点总结一遍。

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

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

###19.03_异常(try...catch的方式处理异常1)
* A:异常处理的两种方式
    * a:try…catch…finally
        * try catch
        * try catch finally
        * try finally 
    * b:throws
* B:try...catch处理异常的基本格式
    * try…catch…finally
* C:案例演示
    * try...catch的方式处理1个异常

###19.04_异常(try...catch的方式处理异常2)
* A:案例演示
    * try...catch的方式处理多个异常
    * JDK7以后处理多个异常的方式及注意事项

###19.05_异常(编译期异常和运行期异常的区别)
* A:编译期异常和运行期异常的区别
    * Java中的异常被分为两大类:编译时异常和运行时异常。
    * 所有的RuntimeException类及其子类的实例被称为运行时异常,其他的异常就是编译时异常
    
    * 编译时异常
        * Java程序必须显示处理,否则程序就会发生错误,无法通过编译
    * 运行时异常
        * 无需显示处理,也可以和编译时异常一样处理
* B:案例演示
    * 编译期异常和运行期异常的区别

###19.06_异常(Throwable的几个常见方法)
* A:Throwable的几个常见方法
    * a:getMessage()
        * 获取异常信息,返回字符串。
    * b:toString()
        * 获取异常类名和异常信息,返回字符串。
    * c:printStackTrace()
        * 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
* B:案例演示
    * Throwable的几个常见方法的基本使用

###19.07_异常(throws的方式处理异常)
* A:throws的方式处理异常
    * 定义功能方法时,需要把出现的问题暴露出来让调用者去处理。
    * 那么就通过throws在方法上标识。
* B:案例演示
    * 举例分别演示编译时异常和运行时异常的抛出

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

###19.09_异常(finally关键字的特点及作用)
* A:finally的特点
    * 被finally控制的语句体一定会执行
    * 特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))
* B:finally的作用
    * 用于释放资源,在IO流操作和数据库操作中会见到
* C:案例演示
    * finally关键字的特点及作用

###19.10_异常(finally关键字的面试题)
* A:面试题1
    * final,finally和finalize的区别
* B:面试题2
    * 如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问是在return前还是return后。
    
###19.11_异常(自定义异常概述和基本使用)
* A:为什么需要自定义异常
    * 举例:人的年龄
* B:自定义异常概述
    * 继承自Exception
    * 继承自RuntimeException
* C:案例演示
    * 自定义异常的基本使用

###19.12_异常(异常的注意事项及如何使用异常处理)
* A:异常注意事项
    * a:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
    * b:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
    * c:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws
* B:如何使用异常处理
    * 原则:如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这是用throws
    * 区别:
        * 后续程序需要继续运行就try
        * 后续程序不需要继续运行就throws
        
    * 如果JDK没有提供对应的异常,需要自定义异常。

###19.13_异常(练习)
* 键盘录入一个int类型的整数,对其求二进制表现形式
     * 如果录入的整数过大,给予提示,录入的整数过大请重新录入一个整数BigInteger
     * 如果录入的是小数,给予提示,录入的是小数,请重新录入一个整数
     * 如果录入的是其他字符,给予提示,录入的是非法字符,请重新录入一个整数

###19.14_File类(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对象
* C:案例演示
    * File类的构造方法

###19.15_File类(File类的创建功能)
* A:创建功能
    * public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
    * public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
    * public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来
* B:案例演示
    * File类的创建功能

    * 注意事项:
        * 如果你创建文件或者文件夹忘了写盘符路径,那么,默认在项目路径下。
        
###19.16_File类(File类的重命名和删除功能)
* A:重命名和删除功能
    * public boolean renameTo(File dest):把文件重命名为指定的文件路径
    * public boolean delete():删除文件或者文件夹
* B:重命名注意事项
    * 如果路径名相同,就是改名。
    * 如果路径名不同,就是改名并剪切。
* C:删除注意事项:
    * Java中的删除不走回收站。
    * 要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹


###19.17_File类(File类的判断功能)
* A:判断功能
    * public boolean isDirectory():判断是否是目录
    * public boolean isFile():判断是否是文件
    * public boolean exists():判断是否存在
    * public boolean canRead():判断是否可读
    * public boolean canWrite():判断是否可写
    * public boolean isHidden():判断是否隐藏
* B:案例演示
    * File类的判断功能
    
###19.18_File类(File类的获取功能)
* A:获取功能
    * public String getAbsolutePath():获取绝对路径
    * public String getPath():获取路径
    * public String getName():获取名称
    * public long length():获取长度。字节数
    * public long lastModified():获取最后一次的修改时间,毫秒值
    * public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
    * public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组 
* B:案例演示
    * File类的获取功能

###19.19_File类(输出指定目录下指定后缀的文件名)
* A:案例演示
    * 需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称

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

###19.21_File类(递归)
* 5的阶乘        

###19.22_day19总结
把今天的知识点总结一遍。

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

###20.02_IO流(FileInputStream)
* read()一次读取一个字节

        FileInputStream fis = new FileInputStream("aaa.txt");    //创建一个文件输入流对象,并关联aaa.txt
        int b;                                                    //定义变量,记录每次读到的字节
        while((b = fis.read()) != -1) {                            //将每次读到的字节赋值给b并判断是否是-1
            System.out.println(b);                                //打印每一个字节
        }
        
        fis.close();                                            //关闭流释放资源
###20.03_IO流(read()方法返回值为什么是int)
* read()方法读取的是一个字节,为什么返回是int,而不是byte

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

        FileOutputStream fos = new FileOutputStream("bbb.txt");    //如果没有bbb.txt,会创建出一个
        //fos.write(97);                        //虽然写出的是一个int数,但是在写出的时候会将前面的24个0去掉,所以写出的一个byte
        fos.write(98);
        fos.write(99);
        fos.close();
###20.05_IO流(FileOutputStream追加)
* A:案例演示
    * FileOutputStream的构造方法写出数据如何实现数据的追加写入

        FileOutputStream fos = new FileOutputStream("bbb.txt",true);    //如果没有bbb.txt,会创建出一个
        //fos.write(97);                        //虽然写出的是一个int数,但是在写出的时候会将前面的24个0去掉,所以写出的一个byte
        fos.write(98);
        fos.write(99);
        fos.close();

###20.06_IO流(拷贝图片)
* FileInputStream读取
* FileOutputStream写出

        FileInputStream fis = new FileInputStream("致青春.mp3");    //创建输入流对象,关联致青春.mp3
        FileOutputStream fos = new FileOutputStream("copy.mp3");//创建输出流对象,关联copy.mp3
        
        int b;
        while((b = fis.read()) != -1) {
            fos.write(b);
        }
        
        fis.close();
        fos.close();
        

###20.07_IO流(拷贝音频文件画原理图)
* A:案例演示
    * 字节流一次读写一个字节复制音频
* 弊端:效率太低

###20.08_IO流(字节数组拷贝之available()方法)
* A:案例演示
    * int read(byte[] b):一次读取一个字节数组
    * write(byte[] b):一次写出一个字节数组
    * available()获取读的文件所有的字节个数
* 弊端:有可能会内存溢出 
    
        FileInputStream fis = new FileInputStream("致青春.mp3");
        FileOutputStream fos = new FileOutputStream("copy.mp3");
        byte[] arr = new byte[fis.available()];                    //根据文件大小做一个字节数组
        fis.read(arr);                                            //将文件上的所有字节读取到数组中
        fos.write(arr);                                            //将数组中的所有字节一次写到了文件上
        fis.close();
        fos.close();
        
###20.09_IO流(定义小数组)
* write(byte[] b)
* write(byte[] b, int off, int len)写出有效的字节个数

        
###20.10_IO流(定义小数组的标准格式)
* A:案例演示
    * 字节流一次读写一个字节数组复制图片和视频
        FileInputStream fis = new FileInputStream("致青春.mp3");
        FileOutputStream fos = new FileOutputStream("copy.mp3");
        int len;
        byte[] arr = new byte[1024 * 8];                    //自定义字节数组
        
        while((len = fis.read(arr)) != -1) {
            //fos.write(arr);
            fos.write(arr, 0, len);                            //写出字节数组写出有效个字节个数
        }
        
        fis.close();
        fos.close();
###20.11_IO流(BufferedInputStream和BufferOutputStream拷贝)
* A:缓冲思想
    * 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,
    * 这是加入了数组这样的缓冲区效果,java本身在设计的时候,
    * 也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流
* B.BufferedInputStream
    * BufferedInputStream内置了一个缓冲区(数组)
    * 从BufferedInputStream中读取一个字节时
    * BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个
    * 程序再次读取时, 就不用找文件了, 直接从缓冲区中获取
    * 直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个
* C.BufferedOutputStream
    * BufferedOutputStream也内置了一个缓冲区(数组)
    * 程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中
    * 直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里
* D.拷贝的代码 

        FileInputStream fis = new FileInputStream("致青春.mp3");            //创建文件输入流对象,关联致青春.mp3
        BufferedInputStream bis = new BufferedInputStream(fis);            //创建缓冲区对fis装饰
        FileOutputStream fos = new FileOutputStream("copy.mp3");        //创建输出流对象,关联copy.mp3
        BufferedOutputStream bos = new BufferedOutputStream(fos);        //创建缓冲区对fos装饰
        
        int b;
        while((b = bis.read()) != -1) {        
            bos.write(b);
        }
        
        bis.close();                        //只关装饰后的对象即可
        bos.close();
     
* E.小数组的读写和带Buffered的读取哪个更快?
    * 定义小数组如果是8192个字节大小和Buffered比较的话
    * 定义小数组会略胜一筹,因为读和写操作的是同一个数组
    * 而Buffered操作的是两个数组

###20.12_IO流(flush和close方法的区别)
* flush()方法
    * 用来刷新缓冲区的,刷新后可以再次写出 
* close()方法
    * 用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出 
###20.13_IO流(字节流读写中文) 
* 字节流读取中文的问题
    * 字节流在读中文的时候有可能会读到半个中文,造成乱码 
* 字节流写出中文的问题
    * 字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组 
    * 写出回车换行 write("\r\n".getBytes());

###20.14_IO流(流的标准处理异常代码1.6版本及其以前)
* try finally嵌套

        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("aaa.txt");
            fos = new FileOutputStream("bbb.txt");
            int b;
            while((b = fis.read()) != -1) {
                fos.write(b);
            }
        } finally {
            try {
                if(fis != null)
                    fis.close();
            }finally {
                if(fos != null)
                    fos.close();
            }
        }

###20.15_IO流(流的标准处理异常代码1.7版本)
* try close

        try(
            FileInputStream fis = new FileInputStream("aaa.txt");
            FileOutputStream fos = new FileOutputStream("bbb.txt");
            MyClose mc = new MyClose();
        ){
            int b;
            while((b = fis.read()) != -1) {
                fos.write(b);
            }
        }
* 原理
    * 在try()中创建的流对象必须实现了AutoCloseable这个接口,如果实现了,在try后面的{}(读写代码)执行后就会自动调用,流对象的close方法将流关掉 

###20.16_IO流(图片加密)
* 给图片加密

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.jpg"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.jpg"));
        
        int b;
        while((b = bis.read()) != -1) {
            bos.write(b ^ 123);
        }
        
        bis.close();
        bos.close();

###20.17_IO流(拷贝文件)
* 在控制台录入文件的路径,将文件拷贝到当前项目下

        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个文件路径");
        String line = sc.nextLine();                //将键盘录入的文件路径存储在line中
        File file = new File(line);                    //封装成File对象
        FileInputStream fis = new FileInputStream(file);
        FileOutputStream fos = new FileOutputStream(file.getName());
        
        int len;
        byte[] arr = new byte[8192];                //定义缓冲区
        while((len = fis.read(arr)) != -1) {
            fos.write(arr,0,len);
        }
        
        fis.close();
        fos.close();

###20.18_IO流(录入数据拷贝到文件)
* 将键盘录入的数据拷贝到当前项目下的text.txt文件中,键盘录入数据当遇到quit时就退出

        Scanner sc = new Scanner(System.in);
        FileOutputStream fos = new FileOutputStream("text.txt");
        System.out.println("请输入:");
        while(true) {
            String line = sc.nextLine();
            if("quit".equals(line))
                break;
            fos.write(line.getBytes());
            fos.write("\r\n".getBytes());
        }
        
        fos.close();
###20.19_day20总结
* 把今天的知识点总结一遍。

你可能感兴趣的:(Java总结)