00_java进阶笔记

_01_Object类

/*
* java.util.Object Object类是最顶层的类,每个类都使用Object类作为父类
*                           所有对象(包括数组)都实现这个类的方法
*     注:
*       使用toString方法返回值为地址值时,说明该对象没有重写toString方法。
*       返回值非地址值,则该对象重写了toString方法
*
*
* */
/*
* boolean equals(Object obj)
*   Object obj  :表示可以传递任何值
*   基本类型:比较数值
*   引用类型:比较地址值
*    public boolean equals(Object obj) {
        return (this == obj);
    }

    比较地址没有意义,所以对equals方法进行重写
* */
/*
* 1 Object :所有类的父类,一个类直接或间接的继承这个类,该类提供常用的方法
* 2 toString方法:
*       打印对象的信息
*       重写前:打印:包名@地址值
*       重写后:打印:对象中的属性值
* 3 equals方法:
*       比较两对象
*       重写前:比较对象地址值
*       重写后:比较对象中的属性值
*
* Objects类:
*   equals方法:比较对象是否相同,添加了一些健壮性的判断
* */

_02_Date类

/*
*java.util.Date;   //表示特点给的瞬间,精确到毫秒
*       毫秒:1000毫秒 = 1秒
*       毫秒值的作用:可以对时间和日期的计算
*                   日期转毫秒,计算后毫秒转日期
*                   0毫秒值:1970年1月1日 00:00:00(英国格林威治)
*                       注:中国属于东八区,时间加8小时
*                   1天 = 24h X 60min X 60 second = 86400s = 86400 X 1000 毫秒 = 8640000毫秒
*       System.currentTimeMillis();  //返回当前之间到1970.1.1 的毫秒时间
*       Date(); //获取当前日期和时间
*
* */
/*
* java.text.DateFormat; //日期/时间格式化子类的抽象类,完成日期和文本之间的转换,在Date对象和String对象之间转换
*           格式化:Date对象转String对象
*           解析:String对象转Date对象
*     成员方法:
*           String format(Date date)   //按照指定模式,将日期类型转化为符合模式的字符串输出
*           Date parse(String  source) throws ParseException// 把符合模式的字符串,解析为Date日期
*                   pause声明解析 异常
*                   处理:1 继续抛出异常
*                        2 try ……catch自己处理异常
*           注:DateFormat类是个抽象类,无法创建对象使用,所以使用其子类SimpleDateFormat类
*     SimpleDatemat类的构造方法:java.text.SimpleDatemat extends DateFormat
*           SimpleDateFormat (String pattern) //用给定的模式和语言环境的日期格式符号构造
*           参数 : String pattern  //传递指定的参数
*           模式:区分大小写
*               y   年
*               M   月
*               d   日
*               H   时
*               m   分
*               s   秒
*            注:模式中的字母不可更改,连接符可以更改 例:“yyyy年MM月dd日 HH:mm:ss”  //“yyyy-MM-dd HH时mm分ss秒”
 *
*
* */

_03_Calendar类

/*
* java.util.Calendar;   //日历类,替换许多Date方法   为抽象类  需创建子类对象进行使用
*                       //操作日期字段的方法(YEAR、MONTH、DAY_OF_MONTH、HOUR)
*         静态方法:getInstance();//返回Calendar类的子类对象
*                  static Calendar getIstance(); //使用默认时区和语言环境获得一个日历
*         Calendar类的常用成员方法:
*                       public int get (int field){} //返回给定日历字段的值
*                       public void set (int field, int values){} //将给定字段设置给日历字段
*                       public abstract void add(int field , int amount) //给日历字段增加或减少某个值
*                       public Date getTime ();  //将日历字段转换成Date对象
* */

_04_System类

/*
 *java.lang.System  类中提供了大量静态方法,获取与系统相关的信息和系统级操作
 *           常用方法:
 *               public static long currentTimeMillis();  //返回以毫秒为单位的当前时间
 *               public static void arrayCopy (Object src, int srcPos, Object dest, int desPos, int length);
 *               //src:源数组  srcPos:原数组起始位置 dest:目标数组 desPos:目标数组起始位置,length:替换长度
 * */

_05_StringBuilder类

/*

StringBuilder类:字符串缓冲区,提高字符串的操作效率,(长度可以变化的字符串)
                    底层为数组,没有被final修饰,可改变长度
                    byte[] value = new byte[16];  //默认16
                    占用空间少,效率高
                    超出长度,会自动扩容

       构造方法:
            public StringBuilder();//构造一个空的StringBuilder容器
            public StringBuilder(String str);//字符串添加到容器中
       StringBuilder的成员方法:
            public StringBuilder append();//添加任意类型数据的字符串形式,并返回对象自身
            reverse();  //字母的反转
            toString();  //StringBuilder和String之间的转换


*/

_06_包装类

/*
* 包装类:   int        Integer
*           byte        Byte
*           char       Character  等
 * 装箱:基本类型转换为对应的包装类对象
 *      构造方法 :
 *              Integer(int value);  //int 包装为 Integer
 *              Integer (String s);  //String 包装为 int  转换的字符与int类型相对应,否则报错
 *      静态方法:
 *              static Integer valueOf(int i);
 *              static Integer valueOf(String s);
 *
 * 拆箱:包装类 转 基本类型
 *      成员方法:
 *              int intValue();  //以int类型返回该Integer的值
 * 自动拆箱和自动装箱:
 *      Integer int3 = 9;  //自动装箱:Integer int3 = new Integer(9);
        int3 = int3 + 2;//  int3+2 : int3.intValue() + 2 = 11         int3 = new Integer(11);

        //ArrayList无法直接存取整数,可以存储Integer包装类
        System.out.println("=======================");
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);  // add(new Integer(1));
        arrayList.get(0);  //获取0号索引上的Integer类型元素
        int int5 = arrayList.get(0);  //自动拆箱  int int5 = arrayList.get(0).valueOf();
 *
* */

_07_Collection集合

/*
* 集合与数组的区别:
*       1 数组长度固定,集合长度可变
*       2 数组存储一类型元素且能存储基本数据类型,集合存储对象且对象类型可不一致。开发中对象多的时候,使用集合进行存储
*       
* */
/*
学习集合的目的:
        会使用集合存储数据
        会遍历集合
        掌握集合的特性
集合框架的学习方式:
        学习顶层:学习顶层接口/抽象类中的共性的方法,所有子类的使用
        使用底层:底层不是 接口就是抽象类,无法创建对象使用,需要使用底层的子类创建对象使用

Collection集合:
        定义的是所有单列集合中共性的方法
        所有单列集合都可以使用共性的方法
        没有带索引的方法
    List接口:Vector集合、ArrayList集合、LinkedList集合
            有序的集合(存取顺序相同)
            允许存储重复的元素
            有索引,可以使用普通的for循环遍历
    Set接口:Treeset集合(无序)、HashSet集合(LinkedHashSet集合(有序))
            不允许存储重复的元素
            没有索引(无法使用for循环遍历)

List集合:有索引,可存储重复元素,保证存储顺序
    ArrayList:底层数组实现,查询快,增删慢
    LinkedList:底层是链表实现,查询慢,增删快
Set集合:无索引,不可存储重复元素,存取无序
    HashSet:底层是哈希表+(红黑树)实现,无索引,不可存储重复元素,存取无序
    LinkedHashSet:底层是哈希表+链表实现,无索引,不可存储重复元素,存取无序
    TreeSet:底层是二叉树实现,一般用于排序

*/
/*
* Collection集合共性常用方法:
    boolean add(E e);  //向集合中添加元素
    boolean remove(E e);//删除集合中的某个元素
    void clear(); //清空集合
    boolean contains(E e);//查看集合是否包含某个元素
    boolean isEmpty();//判空
    int size();//获取集合的长度
    Object[] toArray();//将集合转换成数组

* */
/*
* Iterator接口(Iterator迭代器):Collection集合元素的通用获取方式,取前判空,有则取,循环往复,无则停止。该方法称之为:迭代
*
* java.util.Iterator接口;迭代器(对集合进行遍历)
*   常用方法:
*           boolean hasNext();//判断是否还有下一个元素,有返回true,没有返回false
*           E next();返回迭代的下一个元素
*   注意事项:
*           Iterator迭代器是一个接口,无法直接使用,需要使用Iterator接口的实现类对象,
*           Collection集合中有个方法iterator(),这个方法返回的是迭代器的实现类对象
*                   Iterator<E> iterator();//返回在collectiond的元素上进行迭代的 迭代器
*  迭代器的使用步骤:
*           使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收
*           使用Iterator接口中的方法hasNext判断是否还有下一个元素
*           使用Iterator接口中的方法next方法取出集合中的下一个元素
*
* */
/*
* 增强for循环:底层使用迭代器,使用for循环格式,简化了迭代器的书写
*       Collection<E>  extends  Iterator<E>   //所有单列集合都可以使用增强for循环
*       public interface   Iterator<T>    //实现这个接口允许对象成为  foreach 语句的目标
* 作用:用来遍历数组和集合
*    格式:
*       for(集合/数组的数据类型  变量名:  集合名/数组) {
*               System.out.println(变量名);
*       }
* */

_08_泛型

/*
* 泛型:一种未知的数据类型,使用泛型
*       泛型也可看做一个变量,用来接收数据
*           E e:Element元素
*           T t:Type类型
*   例如:public class ArrayList<E> {
*           public boolean add(E e) {};
*           public E get (int index) {};
*       }
*   注:创建集合对象的时候,确定泛型的数据类型
*       public class ArrayList<String> {
 *           public boolean add(String e) {};
 *           public String get (int index) {};
 *       }
 *          //将数据类型作为参数传递给泛型
 *       public class ArrayList<Student> {
 *           public boolean add(Student e) {};
 *           public Student get (int index) {};
 *       }
 *
 * 集合对象与泛型的利弊:
 *      集合对象:
 *          好处:集合不使用泛型,默认类型为Object类型,可以存储任意类型的数据
 *          弊端:不安全,会发生异常
 *      泛型:
 *          好处:避免了类型转换的麻烦,存储什么类型就是什么类型
 *          弊端:只能存储一种数据类型
 *
* */
/*含泛型的方法定义  格式:
        修饰符 <E> 返回值类型  方法名 (参数列表(使用泛型))  {
                方法体;
        }
*
* */
/*
* 泛型的通配符:
*       ? //代表任意数据类型
* 使用方法:
*       不能创建对象使用
*       只能作为方法的参数使用
*
* 通配符高级使用:(受限泛型)
*       泛型的上限:
*           格式:类型名称 <? extends 类> 对象名称  //只能接收该类型及其子类
*       泛型的下限:
*           格式:类型名称 <? super 类> 对象名称  //只能接收该类型及其父类型
*     注:已知:Object类,String类,Number类,Integer类,其中Number是Integer的父类
*
* */

_10_数据结构

/*
* 数据存储的常用结构:栈、队列、数组、链表、红黑树
*   栈:先进后出
*   队列:先进先出
*   数组:查询快:首地址 + 索引 快速找到元素
*        增删慢: 数组创建长度固定,增删需重新创建素组,将元素重新加入
*   链表:查询慢: 链表地址不连续,查询元素需要从头开始查询
*        增删快: 链表的增删元素对链表的整体结构没有影响
*      链表状态:  地址1|元素1|地址2 ———— 地址2|元素2|地址3 ————
*      单向链表(无序):链表中只有一条链子,不能保证元素的顺序(存取元素的顺序有可能不同)
*      双向链表(有序):链表中有两条链子,一条专门记录元素的顺序,是一个有序的集合
*   红黑树:
*       排序树/查找树:左子小,右子大
*       *衡树:左右孩子数相等
*       不*衡树:右孩子!=左孩子
*       红黑树:趋*于*衡树,查询速度非常快,查询叶子结点的最大次数和最小次数不能超过2倍
*               约束:
*                   1 结点可红可黑
*                   2 根节点是黑色
*                   3 叶子节点(空结点)是黑色
*                   4 每个红色的结点的子节点是黑色
*                   5 任何一个结点到其每个叶子节点的所有路径上黑色结点数相同
*
* */
/*List接口:
*       Vector集合、LinkedList集合、ArrayList集合
*       */
* java.util.List接口 extends Collection集合
* List接口的特点:
*       有序的集合,存取顺序一致,存123123
*       有索引,包含一些带索引的方法
*       允许存储重复的元素
*List接口中带索引的常用方法
*       public void add (int index, E element) ;//将指定元素添加到指定的位置
*       public E get(int index); // 返回集合中指定位置的元素
*       public E remove(int index); //移除指定位置的元素,返回删除的元素
*       public E set(int index, E element); //指定元素替换指定位置元素,返回替换前的元素
* 注意事项:防止索引越界异常
*   ArrayList集合:存储的结构是数组结构,增删慢,查找快
*   LinkedList集合 implements List接口
*       特点:1 底层是一个链表结构,查询慢,增删快
*            2 包含大量操作首尾元素的方法
*       注:使用LinkedList集合特有的方法,不能使用多态
*       public void addFirst(E e);
*       public void addLast(E e);
*       public void push(E e);//同addFirst(E e)
*
*       public E getFirst(E e);
*       public E getLast(E e);
*
*       public E removeFirst(E e);
*       public E removeLast(E e);
*       public E pop(E e);
*
*       public boolean isEmpty();
*   Vector集合:实现可增长的对象数组
*              单线程,速度较慢。同ArrayList集合
* */
/*
* Set接口:Treeset集合(无序)、HashSet集合(LinkedHashSet集合(有序))
*       HashSet集合:  有序,不重复
*           哈希值:十进制整数,由系统给出(即对象的地址,是个逻辑地址,并非物理地址)
*                   Object类中int hashCode()方法返回该对象的哈希值
*                   public native int hashCode();  //native代表该方法调用本地操作系统的方法
*           HashSet集合存储数据的结构:(哈希表)
*                   哈希表 = 数组 + 链表
*                   哈希表 = 数组 + 红黑树(提高查询的速度)
*                   特点:速度快
*               数据结构:把元素先 进行分组(相同哈希值的元素是一组),由哈希值组成数组机构,链表/红黑树结构把哈希值相同的元素连接在一起
*               存储数据:先计算元素的哈希值,哈希值相同的连接在同一个哈希值数组元素上
*                       注:连接的链表长度超过8,自动转换为红黑树结构
*               哈希冲突:元素不同,哈希值相同。例如:重地 通话  //元素不同,哈希值相同1179395
*       Set集合元素不重复原理:
*           HashSet集合存储元素时:调用add方法时会调用hashCode方法和equals方法,判断元素是否重复
*               注:空集合时,先计算元素1的哈希值,集合中没有时添加元素到集合,再计算元素2的哈希值,集合中有相同哈希值时,再调用
*                   equals方法,比较元素1和元素2是否相同,返回ture时,认定重复元素2不进数组,否则添加到数组。保证HashSet集合中
*                   元素不重复
*       HashSet集合存储自定义元素:
*           Set集合存储的数据(String,Integer,……,Student,Person)时,必须重写hashCode和equals方法,否则不能查重
* */
/*
* java.util.LinkedHashSet集合 extends HashSet集合   无序,不重复
*   LinkedHashSet集合特点:底层是哈希表(数组 + 链表 /红黑树) + 链表:多了一条链表(记录元素存储顺序),保证元素有序
* */
/*
* 可变参数定义格式:
*   使用:只能在方法参数中使用
*   格式:修饰符 返回值类型 方法名 (参数类型  ... 参数变量) {};  //返回值是地址值,底层为数组
*       public static int method(Object...obj){}   //可变参数终极写法  任意参数,任意类型
*  注意事项:
*       1 可变参数只能有一个,且类型相同
*       2 可变参数与其他类型参数同时使用时,放在最后
* */
/*
*java.util.Collections;
*       public static <T> boolean addAll (Collection<T> c, T ... elements); //集合中添加一些元素
*       public static void  shuffle (List<?> list); // 打乱集合顺序
*
*       Public static <T> void  sort(List<T> list); //将集合中元素按照默认规则排序
*
*       Comparable接口跟Compatator接口中方法的区别
*           public static <T> void sort (List<T> list, Comparator <? super T>);  //将集合中元素按指定规则排序
*           Comparable:自己(this)和别人(参数)比较,需要实现Comparable接口中CompateTo方法
*           Comparator:相当于找一个第三方裁判,比较两个
* */

_11_Map集合

/*
* java.util.Map<k, v>接口
*   Map集合的特点:
*       1 是一个双列集合,一个元素包含两个值(键key,值value)
*       2 Map集合中,key和value数据类型可以相同,也可以不同
*       3 key不允许重复,value可以允许重复
*       4 key和value是一一对应的
*   Map接口常用子类:
*       1 java.util.HashMap<k, v>  implements Map<k, v>接口
*               特点:
*                   HashMap底层是哈希表,查询速度快
*                   HashMap是无序 集合,存取顺序可能不一致
*      2 java.util.LinkedHashMap<k, v>集合  extends  HashMap<k, v> 集合
*               特点:
*                   LinkedHashMap集合底层是哈希表+链表(保证迭代顺序)
*                   LinkedHashMap集合是有序集合,存取顺序一致
*  Map接口常用方法:
*       public V put (K key, V value);//将指定的键和指定的值添加到Map集合中
*       public V remove(Object key);//指定键对应的键值对删除,返回被删除的值
*       public V get(Object key);//根据键,获取对应的值
*       boolean containsKey(Object key);//判断集合中是否包含指定的键
 *
*
* */
/*
* Map集合的第一种遍历:
*       Map集合中的方法:Set<k> keyset();//返回此映射中包含的键的视图(即取键变集合)
*       实现步骤:
*           使用Map集合中的keyset方法,将Map集合中的键取出来,存储在Set集合中
*           遍历set集合,遍历集合中每个key
*           通过Map集合中方法get(key),通过key找value
* Map集合的第二种遍历:
*       Map.Entry<k, v> :在Map接口中有一个内部接口Entry
*       作用:Map集合创建的同时创建Entry对象,记录键与值得映射关系
*       步骤:
*           Set<Map.Entry<k, v>>  entryset :把Map集合内部多个entry对象取出存放在set集合中
*           遍历Set集合,获取集合中每个Entry对象
*               Entry对象中得方法:getkey()//获取key
*                                getvalue()//获取value
*
* */
/*
* LinkedHashMap<k, v> extends HashMap<k, v>
*       HashMap<k,v>  ; //元素不允许重复,存储得是无序集合   存取顺序不一致
*       LinkedHashMapM<k, v> ;//元素不允许重复,存储得是有序得集合   存取顺序一致  //哈希表 + 链表(记录元素顺序)的结构
* */
/*
* java.util.Hashtable<k, v> implements Map<k, v> 集合
*       Hashtable:
*           底层是哈希表,一个线程安全的集合,单线程集合,速度慢
*           不能存储null键,null值
*           Hashtable的子类Properties集合是唯一和I/O流相结合的集合
*       HashMap:
*           底层是哈希表,一个线程不安全的集合,多线程集合,速度快
*           能存储null键,null值
*
*
* */
/*
* 分析:
*       使用Scanner获取字符串
*       创建Map集合,key是字符,value是字符出现次数
*       遍历字符串,获取每个字符
*       使用获取到的字符,Map集合中判断key是否存在
*           key存在:
*               通过字符key,获取value(字符个数)
*               value++
*               put(key, value) 新的value存储在集合中
*          key不存在:
*               put(key, 1)
*       遍历Map集合,输出结果
* */
//public class _07_JDK9_of方法 {
//    public static void main(String[] args) {
//        List<String> list = List.of("a", "b", "c", "d");
//        System.out.println(list);
////        list.add("e");//of方法添加元素后,集合不可使用add再添加元素UnsupportedOperationException
//        //Set集合和Map集合不可有重复元素
////        Set<String> set = Set.of("a", "a", "b", "c", "d");//IllegalArgumentException: duplicate element: a
//        Set<String> set = Set.of("a", "b", "c", "d");//无序集合
//        System.out.println(set);
//
////        Map<String, Integer> map = Map.of("张三",15,"李四",15,"王五",15,"张三",15);//IllegalArgumentException: duplicate key: 张三
//        Map<String, Integer> map = Map.of("张三",15,"李四",15,"王五",15,"赵六",15);//无序集合
//        System.out.println(map);
//    }
//}
/*
* List接口,Set接口,Map接口:增添的新静态方法of,可以个集合一次性添加多个元素
* static <E> List<E> of(E……element)
* 使用前提:当集合中的元素确定后,不能再修改(添加元素)
* 注意事项:
*       of方法只适用于List接口、Set接口、Map接口,不适用于接口的实现类
*       of方法的返回值是一个不能改变的集合,不能在使用add/put方法添加元素,会抛出异常
*       Set和Map接口在调用of方法时,不能有重复的元素,否则会抛出异常
*
*
* */

_12_DeBug程序调试

public class _01_Debug程序调试 {
    public static void main(String[] args) {
        show();
    }

    private static void show() {
        for (int i = 0; i < 4; i++) {
            System.out.println(i);
        }
    }
}
/*
* Debug程序调试:让代码逐行执行,查看代码执行过程,调试程序中出现的debug
* s使用方法:
*       行号的左边鼠标点击,添加断点(每个方法的第一行)
*       右键,点击DeBug执行程序
*注意事项:
*       F8:逐行执行程序
*       F7:进入当方法中
*       shift+F8:跳出方法
*       F9:跳到下一个断点,没有则退出程序
*       ctrl+F2:退出debug模式,停止程序
*       Console:切换到控制台
*
* */

_13_斗地主案例

package _01_知识点总结._13_斗地主案例;
/*
* 斗地主案例:
*       准备牌
*       洗牌
*       发牌
*       排序
*       看牌
*
* */

import java.util.*;


public class _01_斗地主案例 {
    public static void main(String[] args) {
        //1  准备牌
        //创建Map集合,存储牌的索引和牌的组合
        HashMap<Integer, String> poker = new HashMap<>();
        //创建ArrayList集合,存储牌的索引
        ArrayList<Integer> pokerIndex = new ArrayList<>();
        //创建2个List集合,存储花色和数字
        List<String> color = List.of("♥", "♠", "♦", "♣");
        List<String> number = List.of("2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3");
        //存储大王小王
        Integer index = 0;
        poker.put(index,"大王");
        pokerIndex.add(index);
        index++;
        poker.put(index,"小王");
        pokerIndex.add(index);
        index++;
        //遍历循环存储剩余牌
        for (String colors : color) {
            for (String numbers : number) {
                poker.put(index, colors + numbers);
                pokerIndex.add(index);
                index++;
            }
        }
        System.out.println(poker);
        System.out.println(pokerIndex);

        //2  洗牌
        Collections.shuffle(pokerIndex);
        System.out.println(pokerIndex);

        //3 发牌
        //定义四个集合,存储玩家123和 底牌
        ArrayList<Integer> wanjia1 = new ArrayList<>();
        ArrayList<Integer> wanjia2 = new ArrayList<>();
        ArrayList<Integer> wanjia3 = new ArrayList<>();
        ArrayList<Integer> dipai = new ArrayList<>();

        for(int i = 0; i < pokerIndex.size(); i++){
            Integer in = pokerIndex.get(i);
            if(i >= 51) {
                dipai.add(in);
            }else if(i % 3 == 0) {
                wanjia1.add(in);
            }else if(i % 3 == 1) {
                wanjia2.add(in);
            }else if(i % 3 == 2) {
                wanjia3.add(in);
            }
        }
        System.out.println(wanjia1);
        System.out.println(wanjia2);
        System.out.println(wanjia3);
        System.out.println(dipai);

        //4 排序
        Collections.sort(wanjia1);
        Collections.sort(wanjia2);
        Collections.sort(wanjia3);
        Collections.sort(dipai);



        //5 看牌 通过索引集合查看Map集合的方法
        lookPoker("张三",poker,wanjia1);
        lookPoker("李四",poker,wanjia2);
        lookPoker("王五",poker,wanjia3);
        lookPoker("底牌",poker,dipai);
       /* //6 抢地主
        System.out.println("抢地主:(Y/y)");
        for(int i = 0 ;i < 3 ;i++) {
            Scanner scanner = new Scanner(System.in);
            String next = scanner.next();
            if(next == "Y" || next == "y"){
                if(i == 0) {
                    for (int i1 = 0; i1 < dipai.size(); i1++) {
                        wanjia1.add(i1);
                    }
                }else{
                    if(i == 1) {
                        for (int i1 = 0; i1 < dipai.size(); i1++) {
                            wanjia2.add(i1);
                        }
                    }else {
                        if(i == 2) {
                            for (int i1 = 0; i1 < dipai.size(); i1++) {
                                wanjia3.add(i1);
                            }
                        }
                    }
                    break;
                }
            }
*/
    }

    private static void lookPoker(String name , HashMap<Integer, String> poker , ArrayList<Integer> list) {
        System.out.print("姓名:" + name + "  ");
        for (Integer key : list) {
            String value = poker.get(key);
            System.out.print(value + " ");
        }
        System.out.println();//一个玩家结束后 换行
    }
}

_14_异常

/*
* 异常:程序执行过程中,出现非正常的情况,导致JVM的非正常停止的
*       面向对象编程中,异常本身是一个类,产生异常就是创建异常对象并抛出一个异常对象
*       Java异常的方式是中断异常
* 异常分类:
*       java.util.Throwable;//该类是所有异常和错误的超类
*               Exception:编译异常,
*                       RunTimeException:运行异常
*                       程序的小毛病,处理异常后能正常运行
*               Error:错误
*                       程序的错误,需修改程序
* 异常产生过程:
*       JVM处理产生的异常
*               JVM根据异常创建异常对象,包括异常产生的:内容原因位置  new ArrayIndexOutOfBoundsException(“3”);
*               在异常产生的方法中不能处理异常 抛出给main方法解决
*       main方法处理异常:
*               main方法接收异常处理逻辑,不能处理抛出给JVM处理
*       JVM接收异常:
*               把异常对象红色打印给控制台
*               JVM中断当前执行的java程序
*
*
/*
* throw关键字:
*       作用:使用throw关键字在指定的方法中抛出指定的异常
*       格式:throw new xxxException(“异常产生的原因”);
*       注意事项:
*               throw关键字必须写在方法的内部
*               throw关键字后边new的对象必须是Exception或者其子类对象
*               throw关键字抛出指定的异常对象,就必须处理这个异常
*                       RunTimeException或其子类对象,可以不处理,欧默认JVM处理(打印异常,中断程序)
*                       throw后创建编译异常(写代码报错),必须处理异常。throws 或者 try …… catch
* */
/*
* throws关键字:异常处理的第一种方式
*   作用:
*           当方法内部抛出异常对象的时候,那么必须处理这个异常
*           throws处理异常,抛出给调用者(调用者不处理,抛出给JVM),最终交给JVM,中断处理
*   使用格式:
*           修饰符 返回值类型 方法名(参数) throws AAAException, BBBException {
*               throw new AAAException(“产生原因”);
*               throw new BBBException(“产生原因”);
*           }
*   注意事项:
*           throws必须写在方法声明处
*           throws关键字后边声明的异常必须是Exception或其子类对象
*           抛出多个异常,就要处理多个异常
*               如果抛出的异常有子类关系,直接声明父类异常即可
*           调用声明异常的方法,就必须处理异常
*                throw给调用者,不处理后给JVM,中断处理
*                try……catch自己处理
*
* */
/*
* try……catch:异常处理第二种,自己处理
*       格式:
*           try{
*               //可能产生异常的代码
*           }catch(异常类型参数){
*               //异常处理逻辑,一般写入日志中
*           }
*           ……
*           catch(异常类型 变量名){
*
*           }
*      注意事项:
*           try抛出多个异常,用多个catch处理这些异常
*           try中抛出异常,catch处理异常后继续执行后续代码
*           try不跑出异常,catch不执行,执行后续代码
* */
/*
* Throwable类中定义了3个异常处理的方法 :
*       String getMessage();//返回throwable 的简短描述
*       String toString();//返回此throwable的详细消息字符串
*       void printStackTrace();//JVM打印异常对象,默认此方法,打印信息最全
* */
/*
* finally代码块:
*       try{
*           //可能出现异常的代码
*       }catch(异常类型 参数){
*           //异常处理逻辑
*       }finally{
*           //无论是否出现异常都会执行的代码
*       }
*
*注意事项:
*       不能单独使用,必须和try一起使用
*       一般用于资源释放(资源回收),无论程序是否出现异常,都会资源释放
* */
/*
*1 多个异常处理方式:
*       多个异常分别处理
*       多个异常一次捕获,多次处理
*           注意事项:
 *               catch定义的异常变量,存在子父类关系,子类异常变量需放在上边
 *              上述:ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException //正确定义,不报错
 *                  若调换位置,出现报错
*       多个异常一次捕获一次处理
*2 如果finall有return语句,一定返回finally中的内容
*
*3 子父类异常注意事项:
*       父类抛出多个异常,子类重写父类方法时,抛出和父类相同的异常/父类异常的子类/不抛出异常
*       父类方法没有抛出异常,子类重写该方法时也不能抛出异常,若抛出异常,只能捕获处理,不能声明抛出
*       注:父类异常什么样,子类异常就什么杨
* */
/*
* 自定义异常类  extends RuntimeException  方法中异常无需处理,异常交给JVM中断处理
* */

_15_多线程

/*
* 并发:两个或多个事件在同一时间段内发生(交替执行)
* 并行:两个或多个事件在同一时刻发生(同时执行)
*
* 进程:内存中运行的程序
*       硬盘ROM(永久存储)  :程序文档存储的地方
*       内存RAM(临时存储)  :程序文档调用到内存,占用内存空间执行程序,称为:进程
*               任务管理器:关闭进程后,进程占用内存空间释放
* 线程(Thread):进程中的一个执行单元,一个进程至少一个线程,一个进程可有多个线程,该应用程序称多线程程序
*       注:一个程序至少一个线程,一个进程可包含多个线程
*       单线程CPU:执行过程,在多个线程之间高速切换执行
*       4核8线程:执行过程,8个线程
*       多个任务之间高速切换执行(速度是单线程的8倍)
* 线程调度:
*       分时调度:所有线程轮流使用CPU使用权,*均分配每个线程占用时间
*       抢占式调度:优先让优先级高的线程使用CPU,优先级相同时随机选择一个线程执行,Java使用的为抢占式调度
*               线程优先级可设置:任务管理器,找到线程右击进行设置优先级
* 主线程:执行主方法(main)的线程
* 单线程程序:java程序只有一个线程,从main方法开始,从上到下执行
*           JVM执行main方法,main方法进入栈内存
*           JVM找操作系统开辟一条main方法到CPU的执行路径
*           CPU通过路径执行main方法,该路劲称:主线程
* */
/*
*创建多线程第一种:创建Thread类的子类
* java.util.Thread类:描述线程 的类,实现多线程,必须继承Thread类
* 实现步骤:
*       创建一个Thread类的子类
*       在该子类中重写Thread类中的run方法,设置线程任务
*       创建该子类对象
*       调用Thread类中的方法start方法,开启新的线程,执行run方法
*               start()方法使得该线程执行:JVM调用run()方法
*               main线程和创建的线程(run方法) 同时并发执行
*                   多次启动一个线程时非法的,特别时线程结束后不能再重新启动
*               java程序的抢占式调度
*
* */
/*
* 获取线程的名称:
*       使用Thread类中的方法getname();   //返回该线程的名称
*       可以先获取当前执行的线程,使用线程getname()获取线程名称
* 设置线程的名字:
*       使用Thread类中的方法setName
*               void setName(String name) 改变线程名称,使用与参数name相同
*       创建一个带参数的构造方法,参数传递线程的名字,调用父类的带参构造方法让父类给子类分配一个Thread对象
* 线程睡眠方法:
*       public static  void  sleep(long millis);//使得当前执行的线程暂停指定毫秒数后执行
*
* */
/*
* 创建多线程第二种:实现Runnable接口
*       java.util.Runnable; //接口应该由那些打算通过某一线程执行其示例的类实现,类必须定义一个称为run的无参数方法
*       java.util.Thread类的构造方法
*               Thread(Runnable target) ;// 分配新的Thread对象
*               Thread(Runnable target, String name);//分配新的Thread对象
* 实现步骤:
*       创建一个Runnable接口的实现类
*       实现类中重写接口Runnable中的run方法,设置线程任务
*       创建一个Runnable接口的实现类对象
*       创建Thread类对象,构造方法中传递Runnable接口的实现类对象
*       调用Thread类中的start方法,开始新的线程执行run方法
*
*
*
* 实现Runnable接口创建多线程程序的好处:
*       避免了单线程的局限性:
*               一个类只能继承一个类,类继承了Thread类后就不能继承其他的类
*               实现了Runnable接口,还可以继承其他的类,实现其他的接口
*       增强了程序的扩展性,降低了程序的耦合性(解耦)
*               实现Runnable接口的方式,将设置线程任务和 开启新的线程进行了分离
*                   实现类中,重写run方法,用来设置线程
*                   创建Thread类对象,调用start()方法,用来开启线程任务
* */
public class _06_匿名内部类创建多线程 {
    public static void main (String[] args) {
        //创建Thread类对象,重写run()方法设置新线程任务,调用start()方法开启新线程任务
        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + " " + i);
                }
            }
        }.start();


        //实现Runnable接口,创建匿名Thread对象,传递Runnable实现类,调用start开启新线程
        Runnable runnable = new Runnable() {   //创建Runnable接口匿名实现类
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + " " + i);
                }
            }
        };
        new Thread(runnable).start();

        //Runnable接口实现类合Thread类对象的合并线程创建
        new Thread(new Runnable(){
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + " " + i);
                }
            }
        }).start();
    }
}
/*
* 匿名内部类实现线程的创建:
*       匿名内部类:简化代码
*           把子类继承父类,重写父类方法,创建子类对象合一步完成
*           把实现类实现接口,重写接口中的方法,创建实现类对象合成一步完成
*       最终产物:子类/实现类对象,没有名字
*       格式:
*               new 父类/接口(){
*                   重写父类/接口方法;
*               };
*
*
* */

_16_线程安全问题

/*
* 线程安全性问题:多线程访问了共享的数据,会产生线程安全性问题
* 产生的原理:调用单个线程时,依次执行,但Thread类start()方法运行run()方法时,线程进入run()执行if语句时,就失去了CPU的控制权
*            便由下一个线程抢到Cpu控制权执行下一个线程,当线程抢占完毕后,均进入run()方法中。
*            程序还要继续执行,进程依次完成后,其中数据利用的时上一个进程产生的结果继续运行
*            所以会出现线程安全性问题(即:t0 出票1 t1出票0 t3出票-1 的情况)
* 解决线程安全性问题的方法:
*           同步代码块
*                   解决线程安全性问题的第一种方案:使用同步代码块
*                   格式:
*                       synchronized(锁对象){
*                           //可能会出现线程安全问题的代码(访问了共享数据的代码)
*                       }
*                   注意事项:
*                       通过代码块中的锁对象,可以使用任意的对象
*                       必须保证多个线程使用的锁对象是同一个
*                       锁对象作用:把同步代码块锁住,只让一个线程在同步代码快中执行
*                   同步技术的原理:
*                       使用了一个锁对象,锁对象叫同步锁,又叫 对象监视器
*                       同步中的线程,没有执行完毕不会释放锁,同步外的线程没有锁进不去线程,需等待上一个线程释放锁才能获取锁执行锁对象
*           同步方法
*                   解决线程安全性问题的第二种方案:同步方法
*                   格式:定义方法的格式
*                       修饰符 synchronized 返回值类型 方法名(参数列表) {
*                           //可能会出现线程安全问题的代码(访问了共享数据的代码)
*                       }
*                   使用步骤:
*                       把访问了共享数据的代码抽取出来,放到一个方法中
*                       在方法上添加 synchronized 修饰符
*                   静态同步方法:
*                       锁对象:不是this,因为this是创建对象后产生的,静态方法优先于对象
*                       静态方法的锁对象是本类的class属性,(class文件对象(反射))
*           锁机制(Lock)
*                    解决线程安全性问题的第二种方案:使用Lock锁
*                    java.util.concurrent.locks.Lock接口
*                    Lock实现提供了比使用synchronized方法和语句可获得更广泛的锁定操作
*                    Lock接口中的方法:
*                       void lock();//获取锁
*                       void unlock();//释放锁
*                    java.util.concurrent.locks.ReentrantLock implments  Lock接口
*                    使用步骤:
*                       在成员位置创建Lock接口的ReentrantLock实现类对象
*                       在可能会出现问题的代码前调用Lock接口中的方法lock获取锁
*                       在可能会出现问题的代码后调用Lock接口中的方法unlock释放锁
*
* */
/*
* NEW        新建状态      至今尚未启动的线程         例:new Thread();  new Thread子类();
* RUNNABLW   运行状态      正在java虚拟机上执行的线程
* BLOCKED    阻塞状态      受阻塞并等待 某个监视器锁的线程处于该状态
* WAITING    无限等待状态   无限期等待另一个线程来执行某一特定的线程
* TIMED_WAITING 休眠状态   等待另一个线程来执行取决于指定等待时间的操作的线程
* TERMINATED 死亡状态      已退出的线程
*
* */
/*
* 线程之间的通信:
*       创建一个顾客线程:高速老板要买包子,调用wait方法,放弃CPU的执行,进入WAITING状态
*       创建一个老板线程:花5s做包子,做好后调用notify方法,唤醒顾客吃包子,
* 注:
*       两个线程用同步代码块抱起来,保证等待和唤醒只能有一个在执行
*       同步使用的锁对象必须保证唯一
*       只有锁对象才能调用wait和notify方法
* Object类中的方法:
*       void wait();//在其他线程调用该对象的notify()或notifyAll()方法前,导致当前线程等待
*       void notify();//唤醒在此对象监视器上等待的单个线程,继续执行wait方法之后的代码
* */
/*
* 进入TimeWaiting(计时等待状态)由两种方式
*       sleep(long m)  ;  //毫秒值结束,进入Runnable/BLOCKEDz状态
*       wait(long m)  ;  //毫秒值结束,没有被notify唤醒,就自动醒来,线程睡醒进入Runnable/Blocked状态
*/
public static void main(String[] args) {
    Object o = new Object();

    //消费者
    new Thread(){
        @Override
        public void run() {
            while(true){
                synchronized(o){
                    System.out.println("老板我要吃包子");
                    System.out.println("正在等包子的顾客……");;
                    try {//进入无限等待状态
                        o.wait();
                    } catch (InterruptedException e) {
                        e.getStackTrace();
                    }
                }
                System.out.println("顾客拿到了包子,开始吃");
                System.out.println("++++++++++++++++++++++");
            }
        }
    }.start();
     //老板类
        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.getStackTrace();
                    }
                    synchronized(o){

                        System.out.println("包子做好了,可以吃包子了");
                        o.notify();
//                        o.notifyAll();
                    }
                }

            }
        }.start();


    }

}

_17_等待唤醒机制

public class _01_线程间通信 {
}
/*
* 线程间通信:多个线程处理同一资源,但处理的动作不一样
* 处理线程间通信的原因:多线程并发执行,CPU随机切换线程,希望多线程有规律的完成一件任务,需要的一些协调通信
* 等待与唤醒机制:多个线程之间的协作机制
*       常用方法:
*           wait
*           notify
*           notifyAll
*       注意事项:
*           wait方法和notify方法必须由同一个锁对象调用(对应的锁对象可通过notify唤醒使用同一个锁对象调用的wait方法后的线程)
*           wait和notify方法属于Object类(锁对象可以是任意对象,任意对象的所属类都继承于Object类)
*           wait和notify要在同步代码块或同步函数中使用(必须通过锁对象调用这两个方法)
*
* */
/*
* 线程池:JDK1.5后提供:
*      java.util.concurrent.Executors:线程池的工厂类,用来生成线程池
*      Executors类中的静态方法:
*           static ExecutorSerive newFixedThreadPool(int nThreads); //创建固定线程数的线程池
*           参数:创建线程池中的线程数量
*           返回值:ExecutorSerive接口,返回的时ExecutorSerive接口的实现类对象,可以使用ExecutorSerive接口接收
*      java.util.concurrent.ExecutorSerive:线程池接口
*           用来从线程池中获取线程,调用start方法 ,执行线程任务
*                   submit(Runnable task); //提交一个Runnable任务用于执行
*           关闭/销毁线程池的方法:
*                   void Shutdown();
* 线程池的使用步骤:
*       使用线程池的工厂类Executors里提供的静态方法newFixedThreadPool生产一个固定线程数的线程池
*       创建一个类,实现Runnable接口,重写run方法,设置线程任务
*       调用ExecutorSerive接口中的方法submit,传递线程任务,开启线程,执行run方法
*       调用ExecutorSerive接口中的方法shutdown,销毁线程池(不建议使用) 销毁后线程无法调用

* */

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class _06_线程池{
    public static void main(String[] args) {
        //线性池工厂类Executors。中静态方法newFixedThreadPool创建线性池
        ExecutorService ex = Executors.newFixedThreadPool(2);

        //调用ExecutorSerive接口中的方法submit,传递线程任务,开启线程,执行run方法
        ex.submit(new _07_RunnableIMP());
        ex.submit(new _07_RunnableIMP());
        ex.submit(new _07_RunnableIMP());
        ex.submit(new _07_RunnableIMP());

        ex.shutdown();  //不建议使用,一但销毁线性池,线程就不能使用
//        ex.submit(new _07_RunnableIMP());//销毁池子后创建线程会报错

    }
}

/*
* 线程池的概念:一个容器,容纳多个线程,其中线程可以反复多次使用。省掉了频繁创建线程的步骤,
* 线程池的优点:
*       降低资源消耗。减少创建销毁线程的次数。
*       提高响应时间。任务到达时,不许等待线程的创建就能立即执行
*       提高线程的可管理性。根据系统承受能力,调整线程池中工作线程数目,防止消耗过多内存。(每个线程约1MB内存)
*
*
* */
public class _08_函数式编程思想 {
    public static void main(String[] args) {
        inVokeCook(new _09_Cook接口测试类() {
            @Override
            public void Cook() {
                System.out.println("匿名接口重写抽象方法执行了");
            }
        });

        //使用Lambda表达式
        System.out.println("===================================");
        inVokeCook(() -> {  System.out.println("匿名接口重写抽象方法执行了");});

        //使用Lambda表达式简写格式
        System.out.println("===================================");
        inVokeCook(() ->   System.out.println("匿名接口重写抽象方法执行了") );
    }

    public static void inVokeCook(_09_Cook接口测试类 cook) {
        cook.Cook();
    }
}
/*
* 面向对象的思想:做一件事情,找能解决这个事情的对象,完成事情
* 函数式编程思想:只要获取到结果,谁做怎么做不中要,重视结果,不重视过程
*
* Lambda标准格式:
*       一些参数
*       一个箭头
*       一段代码
*   格式:(参数列表)->{重写方法的代码};
*   解释:
*       ()  :接口中抽象方法的参数列表,无参空着,有参多参数逗号隔开
*       ->   : 传递,把参数传递给方法体
*       {}  :重写接口的抽象方法
* */
}
/*
* Lambda表达式:可推到,可省略
*       注:凡是根据上下文推到出来的内容,都可以省略书写
* 可省略的内容:
*       (参数列表)  :  括号中参数列表的类型可以省略不写
*                       括号中参数就一个,那么类型和()都可以省略
*       {一些代码}   :  {}中代码只有一行,无论是否有返回值,都可以省略{}  return   ; 三个元素
*                       注:要省略,上述三个元素均省略
*
*
* */

_18_File类

/*
* java.io.File类
*       文件和目录路径名的抽象表示形式。
*       java把电脑中的文件和文件夹分装在一个FIle类中,可以使用FIle类对文件和文件夹进行操作。
*       File类的方法:
*               创建一个文件/文件夹
*               删除文件/文件夹
*               获取文件/文件夹
*               判断文件/文件夹
*               对文件夹进行遍历
*               获取文件的大小
*       File类是一个与系统无关的类,任何的操作系统都可以使用这个类中的方法。
*       重点三个单词:
*           file:文件
*           directory:文件夹/目录
*           path:路径
*
*  File类的静态成员变量:
*       static String pathSeparator 与系统有关的路径分隔符,它被表示为一个字符串
*       static char  pathSeparetorChar 于系统有关的路径分隔符
*       static String separator 与系统有关的名称分隔符,被表示为一个字符串
*        static char  SeparetorChar 于系统有关的名称分隔符
* 操作路径:路径不能写死了
*       C:\develop\a\a.txt   windows
*       C:/develop/a/a.txt   Linux
*       "C:"+ File.separator +"develop"+ File.separator +"a"+ File.separator +"a.txt"
*
* 绝对路径和相对路径:
*       绝对路径:完整的路径,以盘符开始的路径
*                C:\\develop\\a\\a.txt
*       相对路径:简化的路径
*               当前项目的根路径C:\\develop\\a
*               使用当前项目的根路径,路径可以简写:a.txt(可省略项目的根路径)
*       注意:
*               路径不区分大小写
*               路径的文件名分隔符使用\,\为转义字符,\\代表一个普通的放斜杠
* */
/*
* File(String pathname);    //通过将给定路径名称 ,转换为抽象路径名 来创建一个新File实例
*       参数:
*           String pathname;//字符串的路径名称
*           路径可以以文件、文件夹结尾
*           路径可以是相对路径,或绝对路径
*           路径可存在,也可不存在
*           创建file对象,只是把字符串封装为File对象,不考虑路径的真假情况
* File(String parent,String child);
 *       参数:
 *          路径分为两部分
 *          父路径和子路径,可单独写,
 * File(File parent,String child);
 *       参数:
 *          路径分为两部分
 *          父路径和子路径,可单独写
 *       好处:父路径是File类型,可以使用File的方法对路径进行一些操作,再使用路径创建对象
 *
 *           */
/*
* File类获取功能的方法
*       public String getAbsolutePath();  //返回此File的绝对路径名字符串
*               注:无论路径是绝对路径,还是相对路径,该方法返回的是绝对路径。
*       public String getPath();  //将File转换为路径名字符串
*
*      public String getName();  //返回由此File表示的文件或目录的名称
*      public long length(); //返回由此File 表示的文件的长度
*File判断功能的方法:
*       public boolean exists(); //此File文件路径是否存在
*       public Boolean isDirectory();//此File文件路径是否为文件夹结尾
*       public Boolean isFile();// 此File文件路径是否以文件结尾
*               注:磁盘以文件夹或文件结尾,两种情况是互斥的,使用该方法文件路径必须存在
* File类创建删除功能得方法:
*       public boolean createNewFile();//创建一个新的空 文件
*               返回值:true    文件不存在,创建文件,返回true
*                       false   文件存在,不创建文件,返回false
*               注:此方法只能创建文件,不是文件夹
*                   创建文件的路径不许存在,否则会抛出异常
*       public boolean mkdir();//创建单级空文件夹
*       public boolean mkdirs();//即可以创建单级文件夹,也可以创建多级空文件夹
*               返回值:true   文件夹不存在,创建文件夹,返回true
 *                     false   文件夹存在,不创建文件夹,返回false;构造方法中给出的路径不存在放回false
 *               注:此方法只能创建文件夹,不是文件
 *      public boolean delete();//删除文件或目录
 *              返回值:true   文件/目录删除成功,返回true
 *                     false
 *               注:
 *File类中遍历(数组)方法:
 *      String[] list ;  //遍历文件或目录
 *      File[] listFiles; //File封装对象,存入数组
 *              注:隐藏文件/文件夹也可以遍历
 *                  文件/文件路径不存在,返回空指针异常NullPointerException
 *
*
* */
public class _04_递归计算1到n的和 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入计算求和n的值:");
        int n = scanner.nextInt();
        System.out.println(n + "到1的和为:" + sum(n));
    }

    private static int sum(int n) {
        if( n == 1)
            return 1;
        return n + sum(n - 1);
    }
}
public class _06_递归打印多级文件夹 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入需要遍历的磁盘文件夹:");
        String string = scanner.next();
        File file = new File(string);
        getAllFiles(file);
    }

    private static void getAllFiles(File file) {

        File[] files = file.listFiles();
        for (File f : files) {
            if(f.isDirectory()) {
                getAllFiles(f);
            } else {
                System.out.println(f);
            }
        }
    }
}
/*
* File类中由两个与listFiles重载的方法,方法的参数传递就是过滤器
    *
*     File[] listFiles(FileFilter filter);
*               java.io.FileFilter接口:用于抽象路径名(File对象)的过滤器
*                   作用:用来过滤文件(File对象)
 *                  抽象方法:用来过滤的方法
*                           boolean accept(File pathName); // 抽象路径是否包含在某个路径名列表中
*                           参数:File pathName :使用ListFiles方法遍历目录,得到每一个文件对象
*     File[] listFiles(FilenameFilter filter);
 *               java.io.FilenameFilter接口:实现此接口的类实例可用于过滤器文件名
 *                   作用:用来过滤文件名称
 *                  抽象方法:用来过滤的方法
 *                           boolean accept(File dir,String name); // 指定文件是否包含在某一文件列表中
 *                           参数:File dir :构造方法中传递的被遍历的目录
 *                                  String name:获取的每个文件/文件夹的名称
 *
*
* */

_19_字节流字符流

/*
* 字节流: 字节输入流:InputStream   字节输出流:OutputStream
* 字符流: 字符输出流:Reader         字符输出流:Writer
* 流:数据(字符、字节) ,1字符=2字节 ,1字节=8个二进制位
*
* java.io.OutputStream:字节输出流//此抽象类是表示输出字节流的所有类的超类
*       子类共有的方法:
*           public void close();//关闭此输出流并释放与此流相关链的任何系统资源
*           public void flush();//刷新此输出流并强制任何缓冲的输出字节被写出
*           public void write(byte[] b);//将b.length字节从指定的字节数组写入此输出流
*           public void write(byte[] b, int off, int len);//从指定字节数组写入len字节,从偏移量off开始输出到此输出流
*           public abstract void write(int b);//将指定的字节输出流
*      java.io.FileOutputStream extends OutputStream
*           FileOutputStream:文件字节输出流
*           作用:把内存中的数据写入到磁盘文件中
*           构造方法:
*                   FileOutputStream(String name) //创建一个向具有指定名称的文件中写入数据的输出文件流
*                   FileOutputStream(File file)   //创建一个向指定File对象表示的文件中写入数据的文件输出流
*                   参数:
*                           String name :目的地是文件路径
*                           File file  :目的地是文件
*                   作用:
*                           创建一个FileOutputStream对象
*                           根据构造方法参数创建文件/文件路径,创建一个空的文件
*                    会把FileOutputStream对象指向创建好的文件
*       写入数据的原理:java程序 -> JVM(java虚拟机) -> OS -> OS调用写数据的方法 -> 把数据写入到文件
*       字节输出流的使用步骤:
*               创建一个FileOutputStream对象,构造方法中写入传递数据的目的地
*               调用FileOutputStreamd对象中的方法write,把数据写入文件
*               释放资源(流使用会占用内存资源,使用完毕要内存清空,提高效率)
*       文件存储和打开的原理:硬盘中存储的都是字节(8比特位),文件打开的使用查询编码表(字节转换为字符)。
*               0~27:查询ASCII码表
*               其他值:查询系统默认的码表(中文系统GBK)
*               注:UTF-8 中 :3个字节为一个中文  , GBK中:2个字节为一个中文
*       字节输出流的续写和换行:
*               FileOutputStream(String name, Boolean append); //指定name的文件写入数据的输出文件流
*               FileOutputStream(File file, Boolean append); //指定File对象表示的文件写入数据的输出文件流
*               参数:append
*                       true :创建对象不覆盖原文件,在文件末尾续写数据
*                       false:创建一个新文件,覆盖源文件
*               换行:
*                       windows:\r\n
*                       linux:/n
*                       mac:/r
* java.io.InputStream:字节输入流  //此抽象类是表示字节输入流的所有类的超类
*       所有子类的公用方法:
*               int read();//从输入流中读取数据的下一个字节
*               int read(byte[] b);//从输入流中读取一定数量的字节,并将其存储到缓冲区数组b中
*               void close()//关闭输入流并释放所有相关系统资源
*       java.io.FileInputStream extends InputStream
*               FileInputStream:文件字节输入流
*               作用:硬盘文件,读取到内存中使用
*           构造方法:
*                   FileInputStream(String name)
*                   FileInputStream(File file)
*            参数:读取文件的数据源
*                   String name:文件的路径
*                   File file : 文件
*            构造方法的作用:
*                   创建一个FileInputStream对象
*                   把FileInputStream对象指向构造方法中要读取的文件
*       读取数据原理:java程序 -> JVM -> os -> os读取数据的方法 -> 读取数据
*       字节输入流的使用步骤:
*               创建FileInputStream对象,构造方法中绑定要读取的数据源
*               使用FileInputStream对象中的方法read读取文件
*
*
* */
/*
* 字节输入流一次读取多个字节的方法:
*       int read (byte[] b); //从输入流中一次读取一定数量的字节,将其存储在缓冲区数组b中
*       注:
*           方法参数byte[] 的作用:
*               起到缓冲作用,存储每次读取到的多个字节
*               数组 的长度一般定义为1024(1kb),或者1024的倍数
*           方法的返回值int值:
*               每次读取的有效字节个数
*       String类中的构造方法:
*           String(byte[] bytes); //字节数组转换为字符串
*           String(byte[] bytes, int offset, int length);//字节数组一部分转换为字符串,offset:数组的开始索引,length:转换的字节个数
*
* */
public class _04_文件复制案例 {
    public static void main(String[] args) throws IOException {
        long starts = System.currentTimeMillis();
        //创建输出流(写入),输入流(读取)
        FileOutputStream fos = new FileOutputStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\1.jpg");
        FileInputStream fis = new FileInputStream("E:\\Pictures\\屏保\\人物\\0b7ffd649a35f2a363495f1fd59c2d7d.jpg");

        int len = 0 ; //记录有效字节数
        byte[] bytes = new byte[1024];   //字节数组块,缓冲作用,提高效率
        while((len = fis.read(bytes)) != -1) {
            System.out.println(len);  //每次数组读写的有效字节字数
            fos.write(bytes, 0 , len);
        }

        fis.close();
        fos.close();
        long ends = System.currentTimeMillis();
        System.out.println("复制图片所用时间" + (ends-starts) + "毫秒" );
    }
}
/*
* 字符流的使用:在字节输入流中读取中文产生不能一次读多字节的问题引用 字符流
* java.io.Reader;//字符输入流,是字符输入流最顶层的父类,定义了一些共性的成员方法,是一个抽象类
*       共性的成员方法:
*           int read();//读取单个字符并返回
*           int read(char[] cbuf); //一次读多个字符,将字符读入数组
*           void close();//关闭该流,并释放相关系统资源
*       java.io.FileReader extends InputStreamReader extends Reader
*           FileReader:文件字符输入流
*               作用:硬盘文件数据读入内存
*               构造方法:
*                   FileReader(String filename);
*                   FileReader(File file);
*                           参数:读取文件的数据源
*                                   String filename:文件路径
*                                   File file:文件
*                   FileReader构造方法的作用:
*                           创建一个FileReader对象
*                           会把FileReader对象指向要读取的文件
*               字符输入流的使用步骤
*                       创建FileReader对象,参数绑定要读取的数据源
*                       使用FileReader对象中的方法read读取文件
*                       释放资源
*java.io.Write:字符输出流,所有字符输出流最顶层的父类,一个抽象类
*           共性方法:
*                void write (int c) ;//写入单个字符
*                void write (char[] cbuf);//写入字符数组
*                abstract void write(char[] cbuf, int off, int len);// 写入字符数组的一部分
*                void write(String str);//写入字符串
*                void write (String str , int off, int len);//写入字符串的一部分
*                void flush();//刷新该流的缓冲
*                void close();关闭此流,但要先刷新它
*           java.io.FileWrite extends OutputStreamWrite extends Write
*               FileWrite:文件字符输出流
*               作用:内存字符写入文件
*               构造方法:
*                       FileWrite(File file);//根据给定的File对象构造一个FileWrite对象
*                       FileWrite(String filename);//根据给定的文件名构造一个FileWrite对象
*               构造方法的作用:
*                       创建一个FileWrite对象
*                       根据构造方法中传递的文件/文件路径,创建文件
*                       会把FileWrite对象指向创建好的文件
*               字符输出流的使用步骤:
*                       创建FileWrite对象,构造方法中绑定写入数据的目的地
*                       使用FileWrite中的方法Write,把数据写入内存缓冲区中(字符转换为字节的过程)
*                       使用FileWrite中的方法flush,把内存缓冲区中的数据,刷新到文件中
*                       释放资源,(先把内存缓冲区中的数据刷新到文件中)
* */
/*
* flush:刷新缓冲区,流对象可以继续使用
* close:刷新缓冲区,通知系统是释放资源,流对象不能再使用
* */
/*
* 续写,换行:使用2个参数的方法
*       FileWrite(String filename, boolean append)
*       FileWrite(File file, boolean append)
*               参数:append:续写开关,true为续写不创建新文件,falsh创建新文件覆盖源文件
*       换行:
*           windows:\r\n
*           linux:/n
*           mac:/r
* */
public class _08_try_catch_finally处理流异常 {

        public static void main(String[] args) {
            FileWriter fw = null;
           try{
               fw = new FileWriter("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\f.txt");
               for (int i = 0; i < 5; i++) {
                   fw.write("abc\r\n");
                   fw.flush();
               }

           } catch (IOException e) {
               System.out.println(e);
           } finally {
               if(fw != null) {   //增加判断,注:fw=null时不能调用close方法,会抛出空指针异常
                   try {
                       fw.close(); //充当flush方法和close方法
                   } catch (IOException e) {
                       System.out.println(e);
                   }
               }
           }
        }
}
/*
* Properties集合  extends Hashtable<k, v> implement Map<k, v>
*           Properties类表示一个持久的属性集
*           Properties集合是一个唯一和IO流相结合的集合
                      使用Properties集合中的方法store,把集合中的临时数据持久化的写入硬盘中存储
                      使用Proterties集合中的方法load,把硬盘文件读取到集合中是使用
                      操作字符串的特有方法:
                            Object setProperty(String key, String value);//调用hashtable的方法put
                            String getProperty(String key);//通过key找value,相当于Map集合中get(key)
                            Set<String> stringPropertyNames();//返回键集合,该键和对应值是字符串,相当于Map集合keyset方法
            注:
                    属性列表中每个键及其对应值都是字符串
                    Properties集合是双列集合,key和value默认都是字符串
* */
/*
* store方法:集合中的临时数据持久化的写入硬盘文件
*       void store(OutputStream out,String comments);
*       void store(Write write,String comments);
*       参数:
*           OutputStream out:字节输出流,不能写入中文
*           Write write:字符输出流,可以写入中文
*           String comments : 注释,解释说明保存的文件,不能使用中文,会产生乱码,一般使用‘’空字符串
*       使用步骤:
*               创建Properties集合对象,添加数据
*               创建字节输出流/字符输出流,参数绑定输出目的地
*               使用Properties集合中的方法store,把集合中的临时数据写入硬盘存储
*               释放资源
* */
/*
* Properties集合中方法load,把硬盘文件读取到j集合中使用
*       void load(InputStream instream);
*       void load(Reader reader);
*       参数:
*           InputStream instream:字节输入流,不能读取含有中文的键
*           Reader reader:字符输入流,可以读取含有中文的键
*       使用步骤:
*               创建Properties对象
*               使用Properties对象中的方法load
*               遍历Properties集合
*       注:存储键值对的文件中
*           键值对链接默认使用=,空格
*           #进行注释,注释后不能再读取
*           键值对默认为字符串,文件中不加引号
*
* */

_20_缓冲流

/*
* 字节缓冲输入流:给输入流增加一个缓冲区(数组),提高基本输入流的读取效率
*       BufferedInputStream(new FileInputStream())
*
*
*java.io.BufferedOutputStream extends OutputStream
*       BufferedOutputStream:字节缓冲输出流
*       继承父类共性成员方法:
*            public void close();//关闭此输出流并释放与此流相关链的任何系统资源
 *           public void flush();//刷新此输出流并强制任何缓冲的输出字节被写出
 *           public void write(byte[] b);//将b.length字节从指定的字节数组写入此输出流
 *           public void write(byte[] b, int off, int len);//从指定字节数组写入len字节,从偏移量off开始输出到此输出流
 *           public abstract void write(int b);//将指定的字节输出流
 *      构造方法:
 *           BufferedOutputStream(OutputStream out) ;//创建一个新的缓冲输出流,将数据写入指定的底层输出流
 *           BufferedOutputStream(OutputStream out,int size) ;//创建一个新的缓冲输出流,将具有指定大小的缓冲数据写入指定的底层输出流
 *              参数:
 *                  OutputStream out:字节输出流
 *                          可传递FileOutputStream,缓冲流h会给FileOutputStream增加一个缓冲区,提高写入效率
 *                  int size:指定缓冲区的大小
 *      使用步骤:
 *              创建FileOutputStream对象,构造方法中绑定要输出的文件/路径
 *              创建BufferedOutputStream对象,构造方法中传递FileOutputStream对象,提高FileOutputStream的效率
 *              使用BufferedOutputStream对象中方法write方法,将数据写入缓冲区中
 *              使用BufferedOutputStream对象中方法flush方法,将缓冲区数据刷新到文件中
 *              释放资源(先调用Flush,后调用close)
 *
 *java.io.BufferedInputStream extends InputStream
 *       BufferedInputStream:字节缓冲输入流
 *       继承父类共性成员方法:
 *                  int read();//从输入流中读取数据的下一个字节
 *               int read(byte[] b);//从输入流中读取一定数量的字节,并将其存储到缓冲区数组b中
 *               void close()//关闭输入流并释放所有相关系统资源
 *      构造方法:
 *           BufferedInputStream(InputStream in) ;//创建一个新的缓冲输入流,将数据写入指定的底层输入流
 *           BufferedInputStream(InputStream in,int size) ;//创建一个新的缓冲输入流,将具有指定大小的缓冲数据写入指定的底层输入流
 *              参数:
 *                  InputStream in:字节输入流
 *                          可传递FileinputStream,缓冲流h会给FileInputStream增加一个缓冲区,提高读取效率
 *                  int size:指定缓冲区的大小
 *      使用步骤:
 *              创建FileInputStream对象,构造方法中绑定要输出的文件/路径
 *              创建BufferedInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream的效率
 *              使用BufferedInputStream对象中方法read方法,将数据读取到缓冲区中
 *              释放资源(先调用Flush,后调用close)
* */
/*
 *java.io.BufferedWrite extends Writer
 *       BufferedWrite:字符缓冲输出流
 *       继承父类共性成员方法:
 *                void write (int c) ;//写入单个字符
 *                void write (char[] cbuf);//写入字符数组
 *                abstract void write(char[] cbuf, int off, int len);// 写入字符数组的一部分
 *                void write(String str);//写入字符串
 *                void write (String str , int off, int len);//写入字符串的一部分
 *                void flush();//刷新该流的缓冲
 *                void close();关闭此流,但要先刷新它
 *      构造方法:
 *           BufferedWrite(Write out) ;//创建一个使用默认大小输出缓冲区的缓冲字符输出流
 *           BufferedWrite(Write out,int sz) ;//创建一个使用指定大小输出缓冲区的新缓冲字符输出流
 *           参数:
 *                  Write out:字符输出流
 *                          可传递FileWriter,缓冲流会给FileWrite增加一个缓冲区,提高写入效率
 *                  int sz:指定缓冲区的大小
 *      特有方法 :
 *              void newLine();//写入一个行分隔符。根据系统,获取不同的分隔符
 *      使用步骤:
 *              创建字符缓冲输出流对象,构造方法传递字符输出流
 *              调用字符缓冲输出流中方法,write,数据写入到缓冲区
 *              调用字符缓冲输出流中flush方法,刷新缓冲区数据到文件
 *              释放资源
 *
 *
 *
 *java.io.BufferedReader extends Reader
 *       BufferedReader:字符缓冲输入流
 *       继承父类共性成员方法:
 *           int read();//读取单个字符并返回
 *           int read(char[] cbuf); //一次读多个字符,将字符读入数组
 *           void close();//关闭该流,并释放相关系统资源
 *      构造方法:
 *           BufferedReader(Reader in) ;//创建一个默认大小缓冲区的缓冲字符输入流
 *           BufferedReader(Reader in,int sz) ;//创建一个指定大小输入缓冲区的缓冲字符输入流
 *              参数:
 *                  Reader in:字符输入流
 *                          可传递FileReader,缓冲流会给FileReader增加一个缓冲区,提高读取效率
 *                  int sz:指定缓冲区的大
 *      特有方法:
 *              String readLine();//读取一个文本行,读取一行数据
 *                      行的终止符:换行\n  回车\r  或者  回车后直接根换行
 *                      返回值:包含该行内容的字符串,不包含任何终止符,到达流末尾,返回null
 *      使用步骤:
 *              创建字符缓冲输入流,构造方法中传递基本字符输入流
 *              使用字符缓冲输入流中的方法:read/readLine读取文本
 *              释放资源
 *
 *
* */
public class _03_文件编码转换 {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_20_缓冲流\\UTF-8.txt"), "utf-8");
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_20_缓冲流\\UTF-8转换的gbk文件.txt"), "gbk");
        int len = 0 ;
        while((len = isr.read()) != -1) {
            osw.write(len);
        }
        isr.close();
        osw.close();
    }
public class _04_文本内容排序 {
    public static void main(String[] args) throws IOException {
        HashMap<String, String> hm = new HashMap<>();
        BufferedReader br = new BufferedReader(new FileReader("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_20_缓冲流\\in.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_20_缓冲流\\out.txt"));
        String len ;
        while((len = br.readLine()) != null) {
            String[] arr = len.split("\\.");
            hm.put(arr[0] , arr[1] );
        }
        for(String key : hm.keySet()) {
            String value = hm.get(key);
            len = key + "." + value;
            System.out.println(len);
            bw.write(len);
            bw.newLine();
        }
        br.close();
        bw.close();
    }
}
/*
* 创建hashMap集合,存储key和value(序号,和文本)
* 创建字符输入流使用readLine读取文本
* 创建字符输出流
* 切割文本,获取序号和文本
* 切割好的内容存储到hashMap集合中去
* 遍历hashMap集合,key与value拼接
* 使用字符输出流Write方法写入文本
* 释放资源
* */

_21_转换流

package _01_知识点总结._21_转换流;

public class _01_字符编码和字符集 {
}
/*
* 编码:字符-->字节
* 节码:字节-->字符
* 字符编码:自然语言的字符与二进制数之间的对应规则
* 字符集:编码表。一套字符必须有一套编码。常见:ASCII,GBK,Unicode
* 编码引发的问题:读取编码时的不对应关系产生乱码
*
* java.io.OutputStreamWriter extends Writer
*       OutputStreamWriter:字符流通向字节流的通道:使指定charset将要写入流中的字符编码写成字节(能看懂的-->看不懂)
*       继承自父类的共性方法:
*                 void write (int c) ;//写入单个字符
 *                void write (char[] cbuf);//写入字符数组
 *                abstract void write(char[] cbuf, int off, int len);// 写入字符数组的一部分
 *                void write(String str);//写入字符串
 *                void write (String str , int off, int len);//写入字符串的一部分
 *                void flush();//刷新该流的缓冲
 *                void close();关闭此流,但要先刷新它
 *      构造方法:
 *              OutputStreamWriter(OutputStream out);//创建使用默认编码的OutputStreamWrite
 *              OutputStreamWrite(OutputStream out,String charsetName);//创建使用指定字符集的OutputStreamWrite
 *              参数:
 *                      OutputStream out:字节输出流,可以用来写转换之后的字节到文件中
 *                      String charsetName:指定的编码表名称,不去分大小写,(utf-8 GBK)
 *     使用步骤:
 *              创建OutputStreamWrite对象,构造方法中传递字节输出流和指定的编码表名称
 *              使用OutputStreamWrite对象中的方法Write,把字符转换为字节存储到缓冲区中
 *              使用OutputStreamWrite对象中的方法flush方法,把缓冲区数据刷新到文件中
 *              释放资源
 *
 * java.io.InputStreamReader extends Reader
 *       InputStreamReader:字符流通向字节流的通道:使指定charset读取字节并将其节码为字符(看不懂的-->看懂)
 *       继承自父类的共性方法:
 *           int read();//读取单个字符并返回
 *           int read(char[] cbuf); //一次读多个字符,将字符读入数组
 *           void close();//关闭该流,并释放相关系统资源
 *      构造方法:
 *              InputStreamReader(InputStream in);//创建使用默认编码的InputStreamReader
 *              InputStreamReader(InputStream in,String charsetName);//创建使用指定字符集的InputStreamReader
 *              参数:
 *                      InputStream in:字节输入流,读取文件中保存的字节
 *                      String charsetName:指定的编码表名称,不去分大小写,(utf-8 GBK)
 *     使用步骤:
 *              创建InputStreanReader对象,参数传递字节输入流和z指定的编码表名称
 *              使用InputStreamReader中read方法读取文件
 *              释放资源
 *      注意事项:
 *              构造方法中的编码要与文件对应,否则发生乱码
*
* */
package _01_知识点总结._21_转换流;

import java.io.*;

public class _02_转换流 {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_20_缓冲流\\UTF-8.txt"),"utf-8");
        osw.write("你好");
        osw.close();

        OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_20_缓冲流\\GBK.txt"),"GBK");
        osw2.write("你好");
        osw2.close();

        System.out.println("======================");
        InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_20_缓冲流\\GBK.txt"), "gbk");
//        int read = isr.read();
//        System.out.println(read);
        int len = 0 ;
        while ((len = isr.read()) != -1) {
            System.out.println((char)len);
        }
        isr.close();
    }
}
package _01_知识点总结._21_转换流;

import java.io.*;

public class _03_序列化和反序列化 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_21_转换流\\1.txt"));
        oos.writeObject(new _04_Person("张三",18));
        oos.close();

        System.out.println("===============================");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_21_转换流\\1.txt"));
        Object o = ois.readObject();
        System.out.println(o);
        _04_Person o1 = (_04_Person) o;
        System.out.println(o1.getName() + o1.getAge());
    }
}
/*
*   对象序列化:把对象以流的方式,写入到文件中保存,叫写对象
*               ObjectOutputStream:对象的序列化流
*   对象反序列化:文件中保存的对象以流的f方式读取出来,叫读对象
*               ObjectInputStream:对象的反序列化
*
*   java.io.ObjectOutputStream extends OutputStream
*           ObjectOutputStream:对象的序列化流
*           作用:把对象以流的方式写入文件中保存
*           构造方法:
*                   ObjectOutputStream(OutputStream out);//创建写入指定OutputStream的ObjectOutputStream
*                   参数:
*                           OutputStream out:字节输出流
*          特有方法:
*               void writeObject(Object obj);//将指定对象写入到ObjectOutputStream
*          使用步骤
*                   创建ObjectOutputStream对象,参数传递字节输出流
*                   使用ObjectOutputStream对象中方法writeObject,把对象写入到文件中
*                   释放资源
*          注意事项:
*               序列化和反序列化时,会抛出NotSerializableException 没有序列化对象
*               类通过实现java.io.Serializable接口启动序列化功能,未实现此接口的类无法使用序列化和反序列化
*               Serializable也叫标记型接口:
*                       进行序列化和反序列化时,必须实现Serializable,就会给l类添加一个标记
*                                       检测标记Serializable接口:
*                                           有:进行序列化和反序列化
*                                           无:抛出NotSerializable异常
*
*
*
 *   java.io.ObjectInputStream extends InputStream
 *           ObjectInputStream:对象的反序列化流
 *           作用:把对象以流的方式从文件中读出
 *           构造方法:
 *                   ObjectInputStream(InputStream in);//创建写入指定InputStream的ObjectInputStream
 *                   参数:
 *                           InputStream out:字节输入流
 *          特有方法:
 *               void readObject(Object obj);//从ObjectInputStream读取对象
 *          使用步骤
 *                   创建ObjectInputStream对象,参数传递字节输入流
 *                   使用ObjectInputStream对象中方法readObject,把对象从文件中读出
 *                   释放资源
 *                   使用读取出来的对象
 *          注意事项:
 *               readObject方法声明抛出ClassNotFoundException(class文件找不到异常)
 *               当不存在对象的class文件时抛出异常
 *               反序列化的前提:
 *                      类必须实现Serializable
 *                      必须存在类对应的class文件
*
* */
package _01_知识点总结._21_转换流;

public class _05_static和transient关键字 {
}
/*
* static关键字:
*       静态优先于非静态加载到内存中(静态优先于对象进入内存中)
*       被static修饰的成员变量不能被序列化,序列化的都是对象
*transient:瞬态关键字
*       被transient修饰成员变量,不能被序列化
*
* 序列化冲突异常:
*       JVM反序列化对象时,能找到class文件,但class文件在序列化对象之后发生修改,反序列化操作就会失败,抛出InvalidClassException异常
*               修改class文件后,文件中的序列号与class中的序列化不一致抛出异常
*               解决方法:
*                       定义序列号
*                       private static final  long serialVersionUID = 1L;
* */
package _01_知识点总结._21_转换流;

import java.io.*;
import java.util.ArrayList;

public class _06_序列化集合 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ArrayList<_04_Person> arr = new ArrayList<>();
        arr.add(new _04_Person("张三",15));
        arr.add(new _04_Person("前朝",18));
        arr.add(new _04_Person("万五",13));

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_21_转换流\\2.txt"));
        oos.writeObject(arr);

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_21_转换流\\2.txt"));
        Object o = ois.readObject();

        ArrayList<_04_Person> arrs = (ArrayList<_04_Person>)o;
        for (_04_Person i : arrs) {
            System.out.println(i);
        }
    }
}
/*
* 文件中保存多个对象到集合中,对集合进行序列化和反序列化
*
*    定义一个存储Person对象的ArrayList集合
*    ArrayList集合中存储Person对象
*    创建序列化流ObjectOutputStream对象 ,使用writeObject方法,对集合进行序列化
*    创建反序列化流ObjectInputStream队形,使用readObject方法,进行反序列化
*    把Object类型转换未ArrayList类型
*    遍历ArrayList集合
*    释放资源
*
* */
package _01_知识点总结._21_转换流;

import java.io.*;

public class _07_打印流 {
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps = new PrintStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_21_转换流\\3.txt");
        ps.write(97);
        ps.println(97);
        ps.println('a');
        ps.println("string");
        ps.close();

        System.out.println("我是控制台输出");
        PrintStream ps2 = new PrintStream("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_21_转换流\\4.txt");
        System.setOut(ps2);   //改变输出目的地
        System.out.println("我是输出流缪弟弟输出的内容");
        ps2.close();
    }
}
/*
* java.io.PrintStream;  //打印流
*       特点:
*               只负责数据的输出,不负责数据的读取
*               永远不会抛出IOException
*               有特有的方法  print   println
*       构造方法:
*               PrintStream(File file);//输出目的地是一个文件
*               PrintStream(OutputStream out);//输出目的地是一个字节输出流
*               PrintStream(String filename);//输出目的地是一个文件路径
*       PrintStream extends OutputStream
*       继承自父类的方法:
*            public void close();//关闭此输出流并释放与此流相关链的任何系统资源
 *           public void flush();//刷新此输出流并强制任何缓冲的输出字节被写出
 *           public void write(byte[] b);//将b.length字节从指定的字节数组写入此输出流
 *           public void write(byte[] b, int off, int len);//从指定字节数组写入len字节,从偏移量off开始输出到此输出流
 *           public abstract void write(int b);//将指定的字节输出流
 *     注意事项:
 *          使用继承自父类方法write,就会查询编码表UTF-8
 *          使用特有方法println,就会输入什么打印什么
 *
 *
 *使用System.setOut方法改变输出语句的目的地
 *        static void  setOut(PrintStream out); //参数传递打印流的目的地
 *        默认输出在控制台,使用该方法改变输出目的地为打印流目的地
*
* */

_22_网络编程

package _01_知识点总结._22_网络编程;

public class _01_软件结构 {
}
/*
* C/S结构:客户端/服务器
* B/S结构:浏览器/服务器
* 网络通信协议:
*       位于同一网络链接和通信时需要遵守的规则,数据的传输速率,传输格式,传输步骤。通信双方同时遵守的规则完成数据交换
* TCP/IP协议:传输控制协议/因特网互联协议。定义计算机如何连接网络,以及数据传输标准。包含一系列处理数据通信的协议,采用4层分层模式,每一层呼叫下一层所3
*               提供的协议完成自己的需求
*           应用层:HTTP FTP TFTP SMTP SNMP DNS 负责应用程序的协议
*           传输层:TCP UDP 使用网络程序进行通信
*           网络层:ICMP IGMP IP ARP RARP 网络层时整个TCP/IP的核心,主要用于将传输的数据分组,将分组数据发送到计算机或者网络
*           数据链路层:
*           物理层:由底层网络定义的协议  链路层是用于定义物理传输通道
* 网络通信协议的分类:
*           UDP:用户数据报协议。无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接
*                   UDP协议消耗资源小,通信效率高,偶尔 丢失几个数据包,不影响结果
*                   UDP无连接性,不能保证数据的完整性
*                   数据被限制在64kb以内,超出范围不能发送
*                   数据报:网络传输的基本单位
*          TCP:传输控制协议。面向连接的通信协议,传输数据前发送端和接收端建立逻辑连接,然后传输数据,保证数据无差错
*               三次握手:客户端向服务器,等待服务器来凝结
*                           服务器向客户端,通知客户端受到请求
*                           客户端向服务器,发送确认信息,确认连接
* 网络编程三要素:
*       协议:计算机网络通信遵守的规则
*       IP地址 :互联网协议地址,为网络中计算机设定唯一编号
*               IP地址分类:
*                   IPV4:4字节,32位,a.b.c.d 范围:0~255 42亿至多
*                   IPV6:16字节,128位,
*               查看本机 IP地址:cmd窗口ipconfig
*               检查网络是否联通:ping IP地址
*       端口号:逻辑端口,用软件查看
*               使用网络软件时,操作系统会给网络软件分配随机端口号,或者网络软件打开时向系统要指定的端口号
*               端口号由两个字节组成,0-65535之间
*               注:
*                       1024之前端口号不能使用,已分配给已知的网络软件
*                       网络软件的端口号不能重复
*                常用端口号:
*                   80端口   http:www.baidu.com:80
*                   数据库  mysql:3306 oracle:1521
*                   Tomcat服务器:8080
*  TCP协议:
*       通信步骤:
*           服务器端先启动
*           使用客户端请求服务器端
*           客户端和服务器端建立一个逻辑连接
*           连接中包含的对象IO对象
*           客户端服务器通过IO对象进行通信
*           IO对象是字节流
*       客户端:Socket类    服务器端:ServeSocket类
*       客户端于服务器端进行一次数据交互,需要四个IO流对象
*               客户端:OutputStream  InputStream
*               服务器端:InputStream OutputStream
*       服务器端注意事项:
*              多客户端与服务器端交互,服务器端accept方法获取请求 的客户端对象
*              服务器没有IO流,通过accept方法 获取客户端队形后使用客户端的流与客户端交互
* */
package _01_知识点总结._22_网络编程;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class _02_TCPClient代码实现 {
    public static void main(String[] args) throws IOException {
        //创建客户端对象Socket
        Socket socket = new Socket("192.168.43.9",6666);

        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("你好服务器".getBytes());

        InputStream inputStream = socket.getInputStream();

        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = inputStream.read(bytes)) != -1) {

            System.out.println(new String (bytes,0,len));
        }
        socket.close();
    }
}
/*
* 表示客户端的类:
*       java.net.Socket;//套接字:两台机器通信的端口 包含了IP地址和端口号的网络单位
*             构造方法:
*                   Socket(String host, int port)
*                   参数:
*                           String host:服务器主机的名称/服务器的IP地址
*                           int port :服务器的端口号
*             成员方法:
*                   OutputStream getOutputStream();//返回此套接字的输出流
*                   InputStream getInputStream();//返回此套接字的输入流
*                   void close();//关闭此套接字
*             实现 步骤:
*                   创建客户端对象Socket,构造方法绑定服务器IP地址和端口号
*                   使用Socket对象getOutputStream()获取网络字节输出流OutputStream对象
*                   使用OutputStream队形中方法Write,
*                   使用Socket对象getinputStream()获取网络字节输出流InputStream对象
 *                  使用InputStream队形中方法read,读取服务器会写的数据
 *                  释放资源(Socket)
 *             注意事项:
 *                  客户端和服务器端进行交互,必须使用Socket中提供的网络流,不能使用自己创建的流对象
 *                  创建客户端对象Socket时,去请求服务器和服务器进行三次握手连接通路
 *                          服务器未启动,抛出异常
 *                          服务器启动,则进行交互
*
* */
package _01_知识点总结._22_网络编程;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class _03_TCPServe代码实现 {
    public static void main(String[] args) throws IOException {
        //创建服务器端
        ServerSocket serverSocket = new ServerSocket(6666);
        Socket accept = serverSocket.accept();

        /*InputStream inputStream = accept.getInputStream();
        byte[] bytes = new byte[1024];
        int len = 0;
        while((len = inputStream.read(bytes)) != -1) {
            System.out.println(new String(bytes, 0,len));
        }*/

        OutputStream outputStream = accept.getOutputStream();
        outputStream.write("受到,你好客户端01".getBytes());

        accept.close();
        serverSocket.close();
    }
}
/*
* 表示服务器的类:
*         java.net.ServerSocket;//此类实现服务器套接字
*               构造方法:
*                       ServerSocket(int  port);
*                       参数:特定端口服务器套接字
*               服务器端使用方法accept获取哪个客户端在请求服务端
*               c成员方法:
*                       Socket accept();监听并接收到此套接字的连接
*               服务器使用步骤:
*                       创建服务器端ServerSocket对象并和系统要指定端口号
*                       使用ServerSocket的方法accept,获取客户端对象Socket
*                       使用getOutputStream,获取输出流,使用方法Write向客户端会消息
*                       使用getInputStream,获取输入流,使用方法read读取客户端发来的请求
*                       释放资源(Socket,ServerSocket)
* */
package _01_知识点总结._22_网络编程;

public class _04_TCP文件上传案例 {
}
/*
* 客户端使用本地字节输入流,读取本地文件
* 客户端使用网络字节输出流,把文件上传到服务器
* 服务器使用网络字节输入流,读取本地上传的文件
* 服务器使用本地 字节输出流,把文件保存到服务器硬盘上
* 服务器使用网络字节输出流,给客户端会写消息,上传成功
* 客户端使用网络字节输入流,读取服务器发来的消息
* 释放资源
*
*
* 注意事项:
*       客户端与服务器进行本地硬盘的读写,使用本地字节流(本地流)
*       客户端与服务器之间进行读写,必须使用Socket提供的字节流对象(网络流 )
*文件上传本质:文件复制
* */
package _01_知识点总结._22_网络编程;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class _05_TCPClient案例 {
    public static void main(String[] args) throws IOException {

        FileInputStream fis = new FileInputStream("E:\\Pictures\\屏保\\车辆\\2002012.jpg");//创建本地字节输入流

        Socket socket = new Socket("192.168.43.9",5555); //创建Socket对象

        OutputStream os = socket.getOutputStream();//获取网络输出流
        System.out.println("33333333333333333333333333333333");
        byte[] bytes = new byte[1024];
        int len = 0;
        while((len = fis.read(bytes)) != -1) {
            os.write(bytes,0,len);
        }
        socket.shutdownOutput();//终止上传


        InputStream is = socket.getInputStream(); //获取网络输入流
        byte[] byte2 = new byte[1024];
        int len2 = 0;
        while((len2 = is.read(byte2)) != -1) {
            System.out.println(new String(byte2));;
        }

        System.out.println("4444444444444444444444444444444444");

        fis.close();
        socket.close();
    }
}
package _01_知识点总结._22_网络编程;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class _06_TCPServer案例 {
    public static void main(String[] args) throws IOException {

        ServerSocket serverSocket = new ServerSocket(5555);//创建服务器对象

        while(true) {  //服务器始终开启状态
            Socket accept = serverSocket.accept(); //获取客户端对象

            new Thread(new Runnable() {   //多线程,提高文件上传效率
                @Override
                public void run() {
                    try{
                        //判断文件夹是否存在
                        File file = new File("E:\\IJ              项目练习\\Java 进阶\\02_进阶\\src\\_01_知识点总结\\_22_网络编程\\模拟服务器硬盘");
                        if(!file.exists()) {
                            file.mkdirs();  //创建文件夹
                        }

                        InputStream is = accept.getInputStream();//获取网络输入流

                        System.out.println("111111111111111111111111111111111111");

                        //自定义命名规则
                        String filename = "Zjj" + System.currentTimeMillis() + ".jpg";
                        FileOutputStream fos = new FileOutputStream(file + "\\" +filename);//创建本地输出流
                        byte[] bytes = new byte[1024];
                        int len = 0;
                        while((len = is.read(bytes)) != -1) {
                            fos.write(bytes,0,len);
                        }


                        System.out.println("222222222222222222222222222222222222");
                        OutputStream os = accept.getOutputStream();
                        os.write("上传成功".getBytes());

                        accept.close();
                        fos.close();
                    } catch (IOException e) {
                        System.out.println(e);
                    }
                }
            }).start();
        }

    }
}
/*
* 注意事项:
*       read方法,读取不到数据会进入死循环状态
*       ServerSocket网络输入流read读取不到文件末尾-1,进去死循环
*       Socket网络输入流read读取不到服务器消息,进入死循环
* 解决方法:
*       文件读取完毕后,添加方法shutdownOutput();//终止文件的写入,结束文件上传
* */
package _01_知识点总结._22_网络编程;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class _07_模拟BS服务器 {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(8080);


        while(true){
            Socket socket = ss.accept();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try{
                        InputStream is = socket.getInputStream();
       /* byte[] bytes = new byte[1024];
        int len = 0;
        while ( (len = is.read(bytes)) != - 1)
            System.out.println(new String(bytes ,0, len));  //GET /WEB/123.htm HTTP/1.1*/

                        BufferedReader bis = new BufferedReader(new InputStreamReader(is));  // 读取字符流GET /WEB/123.htm HTTP/1.1
                        String s = bis.readLine();//读取第一行  GET /WEB/123.htm HTTP/1.1
                        String[] arr = s.split(" ");//空格切割字符串
                        String htmname = arr[1].substring(1);//切割字符串 获取从数组1开始到结束

                        FileInputStream fis = new FileInputStream(htmname);  //创建本地字节输入流
                        OutputStream os = socket.getOutputStream();//获取网络输出流

                        //写入http协议
                        os.write("HTTP/1.1 200 OK\r\n".getBytes());
                        os.write("Content - Type:text/html\r\n".getBytes());
                        os.write("\r\n".getBytes());

                        byte[] bytes = new byte[1024];
                        int len =0;
                        while ((len = fis.read(bytes)) != -1) {
                            os.write(bytes,0,len);
                        }

                        fis.close();
                        socket.close();


                    }catch(IOException e){
                        System.out.println(e);
                    }
                }
            }).start();
        }

//        fis.close();
//        socket.close();
//        ss.close();
    }

}

_23_函数式接口

package _01_知识点总结._23_函数式接口;

@FunctionalInterface
public interface _01_函数实接口的概念 {
    public abstract void method();
}
/*
* 函数式接口:有且仅有一个抽象方法的接口(可含有其他方法 默认 静态 私有)
*       java中的函数式编程思想体现就是lambda
*       语法糖:指使用更加方便,但是原理不变的代码语法
*               (例:遍历集合的for-each,底层实现原理任然是迭代器。java的lambda可作为匿名内部类的语法糖,但二者原理不同)
*                       注:lambda表达式没有.class文件,效率比匿名内部类更高
*       格式:
*           修饰符 interface 接口名称 {
*               public abstract 返回值类型 方法名称(可选参数信息);
*           }
*       函数式接口的注解:@FunctionalInterface
*               检测接口是否时一个函数式接口
*               是:编译成功
*               否:编译失败 (对个抽象方法或没有抽象方法)
*
* */
package _01_知识点总结._23_函数式接口;

@FunctionalInterface
public interface _02_FunctionalFunction {
    public abstract void method();
}
/*
* 函数式接口:有且仅有一个抽象方法的接口(可含有其他方法 默认 静态 私有)
*       java中的函数式编程思想体现就是lambda
*       语法糖:指使用更加方便,但是原理不变的代码语法
*               (例:遍历集合的for-each,底层实现原理任然是迭代器。java的lambda可作为匿名内部类的语法糖,但二者原理不同)
*       格式:
*           修饰符 interface 接口名称 {
*               public abstract 返回值类型 方法名称(可选参数信息);
*           }
*       函数式接口的注解:@FunctionalInterface
*               检测接口是否时一个函数式接口
*               是:编译成功
*               否:编译失败 (对个抽象方法或没有抽象方法)
*
* */
package _01_知识点总结._23_函数式接口;


public class _03_FunctionalFunctionIMPL implements _02_FunctionalFunction{

    @Override
    public void method() {
        System.out.println("函数式接口的实现类");
    }
}
/*
* 函数式接口:有且仅有一个抽象方法的接口(可含有其他方法 默认 静态 私有)
*       java中的函数式编程思想体现就是lambda
*       语法糖:指使用更加方便,但是原理不变的代码语法
*               (例:遍历集合的for-each,底层实现原理任然是迭代器。java的lambda可作为匿名内部类的语法糖,但二者原理不同)
*       格式:
*           修饰符 interface 接口名称 {
*               public abstract 返回值类型 方法名称(可选参数信息);
*           }
*       函数式接口的注解:@FunctionalInterface
*               检测接口是否时一个函数式接口
*               是:编译成功
*               否:编译失败 (对个抽象方法或没有抽象方法)
*
* */
package _01_知识点总结._23_函数式接口;

/*
* 一般作为方法的参数和返回值类型
* */
public class _04_函数式接口的使用 {
    //定义方法,参数使用函数式接口
    public static void show (_02_FunctionalFunction F) {
        F.method();
    }

    public static void main(String[] args) {
        //方法的参数是一个接口,所以可以传递接口的实现类对象
        show(new _03_FunctionalFunctionIMPL());

        show(new _02_FunctionalFunction() {
            @Override
            public void method() {
                System.out.println("函数式接口的匿名参数");
            }
        });

        //匿名方法的lambda表达式
        show(() -> System.out.println("函数式接口的匿名参数lambda表达式"));
    }
}
package _01_知识点总结._23_函数式接口;

public class _05_lambda延迟特性 {
    public static void main(String[] args) {

        String s1 = "hello ";
        String s2 = "word ";
        String s3 = "Java";

        Show(2, () ->{
                System.out. println("不满足不执行字符串凭借");
                return s1 + s2 + s3;
        });
    }

    private static void Show(int level , _06_MessageBuider messageBuider) {
        if(level == 1) {
            String s = messageBuider.buiderMessage();
            System.out.println(s);
        }
    }
}
/*
* 注:使用lambda表达式,只是把参数传递给show方法中
*       满足条件,接口_06_才会调用其中方法,返回字符串拼接的参数 输出
*       不满足条件,接口_06_ ,不会执行其中抽象方法,不会执行抽象方法中的代码,即不会的到返回值
*               所以不存在性能浪费的问题
* */
package _01_知识点总结._23_函数式接口;

@FunctionalInterface
public interface _06_MessageBuider {
    public abstract String buiderMessage();
}
package _01_知识点总结._23_函数式接口;

public class _07_Runnable函数式方法案例 {
    public static void ThreadShow(Runnable run) {
        new Thread(run).start();
    }

    public static void main(String[] args) {
        ThreadShow(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "线程启用了");
            }
        });


        //注:参数使用lambda表达式的前提是,调用的方法传递参数要求是一个函数式接口
        ThreadShow(() -> System.out.println(Thread.currentThread().getName() + "线程启用了")
        );
    }
}
/*
* 注:
*   java.lang.Runnable;//就是一个函数式接口
*   方法参数是一个函数是接口是,传递的参数可以使用lambda表达式,否则不能
* */
package _01_知识点总结._23_函数式接口;

import java.util.Arrays;
import java.util.Comparator;

//java.util.Comparator;是一个函数式接口类型
public class _08_函数式接口做返回值类型 {
    public static Comparator<String> Compare() {
//        return new Comparator<String>() {
//            @Override
//            public int compare(String o1 , String o2) {
//                return o2.length() - o1.length(); //降序排排列
//            }
//        };

        //lambda表达式
        return (String o1 , String o2) -> {return o2.length() - o1.length(); };//降序排排列


        //使用lambda表达式(极简)作为返回值
//        return ( o1 ,  o2) ->
//                 o2.length() - o1.length(); //降序排排列


    }

    public static void main(String[] args) {
        String[] arr = {"e","bbb","cc","aaaaa","dddd"};
        //输出排序前的数组
        System.out.println(Arrays.toString(arr));
        //调用方法排序
        Arrays.sort(arr,Compare());
        System.out.println(Arrays.toString(arr));
    }
}
package _01_知识点总结._23_函数式接口;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class _09_常用的函数式接口 {
    public static String getString(Supplier<String> sup ) {  // Supplier接口作为参数(函数式接口)
        return sup.get();
    }

    public static void method (String name, Consumer<String> consumer) {// Consumer接口作为参数(函数式接口)
        consumer.accept(name);
    }

    public static boolean method2 (String s, Predicate<String> pre) {// Predicate接口作为参数(函数式接口)
        return pre.test(s);
    }

    public static void methods (String num, Function<String, Integer> fun) { // Function接口作为参数(函数式接口)
        Integer apply = fun.apply(num);
        System.out.println(apply);
    }

    public static void main(String[] args) {
        System.out.println(getString(new Supplier<String>() {
            @Override
            public String get() {
                return "胡歌";
            }
        }));
        String string = getString(() -> {
                    return "胡歌";
                }
        );
        System.out.println(string);

        System.out.println("===========================");
        method("zhaoliyin", ( name) ->{
//            System.out.println(name);
            String reverseName = new StringBuffer(name).reverse().toString();  // 字符串翻转
            System.out.println(reverseName);
        });

        System.out.println("=============================");
        boolean result = method2("abcd", (s) -> {
            boolean b = s.length() > 5;
            return b;
        });
        System.out.println(result);

        System.out.println("========================");
        methods("1234" , (String s)->{
            return Integer.parseInt(s);  //包装类Integer的拆箱函数
        });

    }
}
/*
*java.util.function.Supplier<T>接口仅不包含一个无参方法:T get()。用来获取一个泛型参数指定类型的队形数据
*       生产型接口(生产一个数据)
*java.util.Consumer<T>接口与Supplier接口相反,是消耗一个数据
*       抽象方法:void accept(T t);//消费一个指定泛型的数据
*java.util.Predicate<T>接口:对指定泛型的数据进行判断,结果返回一个boolean值
*       抽象方法:boolean(T t);//用来指定泛型数据进行判断
*               符合:返回ture
*               不符合:返回flase
*java.util.function.Function<T,R>;//将T类型数据转换为R类型数据
*       抽象方法:R apply(T t);//
*       例:将String转Integer
*
* */
package _01_知识点总结._23_函数式接口;

import java.util.function.Supplier;

public class _10_Supplier求最大值案例 {
    public static int getMax(Supplier<Integer> supplier ) {
        return supplier.get();
    }

    public static void main(String[] args) {
        int[] arr = { 40, 50 , -10 , 100};
        int max1 = getMax(() -> {
            int max = arr[0];
            for (int i : arr) {
                if (i > max) {
                    max = i;
                }
            }
            return max;
        });
        System.out.println(max1);
    }
}
package _01_知识点总结._23_函数式接口;

import java.util.function.Consumer;

public class _11_Consumer接口中andThen方法 {
    public static void method (String name, Consumer<String> consumer, Consumer<String> consumer2) {
//        consumer.accept(name);
//        consumer2.accept(name);
        consumer.andThen(consumer2).accept(name);  //andThen方法使用同上两句代码

    }

    public static void main(String[] args) {
        method("zhaoliyin", ( name) ->{
//            System.out.println(name);
            String reverseName = new StringBuffer(name).reverse().toString();  // 字符串翻转
            System.out.println(reverseName);
        }, (name) ->{
            String s = name.toLowerCase();
            System.out.println(s);

        });

        /*
         * 注:lambda表达式作为参数传递注意事项:
         *           是先传递,后执行代码
         *           体现了lambda表达式延后执行的特点(提高了代码执行的效率)
         *           避免了资源浪费(先执行代码后,没有使用参数,就存在资源的浪费)
         * */
    }
}
package _01_知识点总结._23_函数式接口;

import java.util.function.Consumer;

public class _12_Consumer接口字符串切割案例 {
    public static void method (String[] arr, Consumer<String> con1, Consumer<String> con2) {
        for (String message : arr) {
            con1.andThen(con2).accept(message);
        }
    }

    public static void main(String[] args) {
        String[] arr = {"赵丽颖,女","迪丽热巴,女","胡亥,男"};
        method(arr,
                (s)->{
                    String[] name = s.split(",");
                    System.out.print("姓名:" + name[0] + "\t\t\t");
                },
                (s)->{
                    String[] name = s.split(",");
                    System.out.println("年龄:" + name[1]);
                 }
                );
        /*
        * 注:lambda表达式作为参数传递注意事项:
        *           是先传递,后执行代码
        *           体现了lambda表达式延后执行的特点(提高了代码执行的效率)
        *           避免了资源浪费(先执行代码后,没有使用参数,就存在资源的浪费)
        * */

    }
}
package _01_知识点总结._23_函数式接口;

import java.util.function.Predicate;

public class _13_Predicate接口中and方法 {
    public static boolean method (String s, Predicate<String> pre1, Predicate<String> pre2 ) {
//        return pre1.test(s) && pre2.test(s);
        return pre1.and(pre2).test(s);
    }

    public static void main(String[] args) {
        String s1 = "abcdef";


        boolean resulet = method(s1, (String s) -> {
            return s.length() > 5;
        }, (String s) -> {
            return s.contains("a");
        });
        System.out.println(resulet);
        /*
         * 注:lambda表达式作为参数传递注意事项:
         *           是先传递,后执行代码
         *           体现了lambda表达式延后执行的特点(提高了代码执行的效率)
         *           避免了资源浪费(先执行代码后,没有使用lambda参数,就存在资源的浪费)
         * */

    }
}
package _01_知识点总结._23_函数式接口;

import java.util.function.Predicate;

/*
* neagte:结果取反函数  相当于逻辑判读!的意思
* */

public class _14_Predicate接口中or和negate {
    public static boolean method (String s, Predicate<String> pre1, Predicate<String> pre2 ) {
//        return pre1.test(s) && pre2.test(s);
//        return !pre1.or(pre2).test(s);  // 整体结果取反
        return pre1.negate().test(s)   || pre2.test(s);  // pre1结果取反
    }

    public static void main(String[] args) {
        String s1 = "abcdef";


        boolean resulet = method(s1, (String s) -> {
            return s.length() > 5;
        }, (String s) -> {
            return s.contains("a");
        });
        System.out.println(resulet);
        /*
         * 注:lambda表达式作为参数传递注意事项:
         *           是先传递,后执行代码
         *           体现了lambda表达式延后执行的特点(提高了代码执行的效率)
         *           避免了资源浪费(先执行代码后,没有使用lambda参数,就存在资源的浪费)
         * */

    }
}
package _01_知识点总结._23_函数式接口;

import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class _14_Predicate接口筛选案例 {
    public static ArrayList<String> method (String[] arr, Predicate<String> con1, Predicate<String> con2) {
        ArrayList<String> arrayList = new ArrayList<>();
        for (String s : arr) {
            boolean test = con1.and(con2).test(s);
            if(test == true) {
                arrayList.add(s);
            }
        }
        return arrayList;

    }

    public static void main(String[] args) {
        String[] arr = {"赵丽颖,女","迪丽热巴,女","胡亥,男"};
        ArrayList<String> arrayResult  = method(arr,
                (String s) -> {
                    String[] sex = s.split(",");
                    if (sex[1].equals("女")) {
                        return true;
                    } else {
                        return false;
                    }
                },
                (String s) -> {
                    return s.split(",")[0].length() == 4;
                }
        );

        for (String s : arrayResult) {
            String[] message = s.split(",");
            System.out.println("姓名:" + message[0] + "\t年龄:" + message[1]);
        }
        /*
         * 注:lambda表达式作为参数传递注意事项:
         *           是先传递,后执行代码
         *           体现了lambda表达式延后执行的特点(提高了代码执行的效率)
         *           避免了资源浪费(先执行代码后,没有使用参数,就存在资源的浪费)
         * */

    }
}
package _01_知识点总结._23_函数式接口;

import java.util.function.Function;

public class _15_Function接口andThen方法 {
    public static void methods (String num, Function<String, Integer> fun1 , Function< Integer,String> fun2) { // Function接口作为参数(函数式接口)
        String s = fun1.andThen(fun2).apply(num);
        System.out.println(s);
    }

    public static void main(String[] args) {
        methods("1234" , (String s)->{
            return Integer.parseInt(s) +10;  //包装类Integer的拆箱函数
        } ,(Integer s)->{
            return s + "";
        });

    }
}
package _01_知识点总结._23_函数式接口;

import java.util.function.Function;

public class _16_Function接口案例 {
    public static void methods (String num, Function<String, String> fun1 , Function< String ,Integer> fun2,
                                Function< Integer,Integer> fun3) { // Function接口作为参数(函数式接口)
        Integer numResult = fun1.andThen(fun2).andThen(fun3).apply(num);
        System.out.println(numResult);
    }

    public static void main(String[] args) {
        methods("照例因,1234" , (String s)->{
            return s.split(",")[1];  //包装类Integer的拆箱函数
        } ,(String string)->{
            return Integer.parseInt(string);
        }, (Integer integer)-> {
            return integer + 100;
        });

    }
}

_24_Stream流

package _01_知识点总结._24_Stream流;

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

public class _01_传统方式遍历集合 {
    public static void main(String[] args) {
        ArrayList<String> lists = new ArrayList<>();
        lists.add("张三丰");
        lists.add("张无极");
        lists.add("张和");
        lists.add("利斯峰");
        lists.add("毛开往");

        ArrayList<String> list2 = new ArrayList<>();
        for (String list : lists) {
            if (list.startsWith("张")) {
                list2.add(list);
            }
        }

        ArrayList<String> list3 = new ArrayList<>();
        for (String s : list2) {
            if(s.length() == 3)
                list3.add(s);
        }

        for (String s : list3) {
            System.out.println(s);
        }
    }
}
package _01_知识点总结._24_Stream流;

import java.util.ArrayList;

public class _02_Stream流方式遍历集合 {
    public static void main(String[] args) {
        ArrayList<String> lists = new ArrayList<>();
        lists.add("张三丰");
        lists.add("张无极");
        lists.add("张和");
        lists.add("利斯峰");
        lists.add("毛开往");

        lists.stream().filter( name -> name.startsWith("张"))
                .filter(name -> name.length() == 3 )
                .forEach(name -> System.out.println(name));
    }
}
package _01_知识点总结._24_Stream流;

import java.util.*;
import java.util.stream.Stream;

public class _03_获取Stream的方式 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();//ArrayList集合转换为Stream流
        Stream<String> listStream = list.stream();

        Set<String> set = new HashSet<>();  //HashSet集合转换为Stream流
        Stream<String> setStream = set.stream();

        Map<String, String> map = new HashMap<>();
        Set<String> mapSet = map.keySet();     //Map集合key的Set集合转换为Stream流
        Stream<String> mapSetStream = mapSet.stream();

        Collection<String> values = map.values();  //Map集合value的Collection集合转换为Stream流
        Stream<String> mapValuesStream = values.stream();

        Set<Map.Entry<String, String>> entries = map.entrySet();   //Map集合映射关系的Set集合转换为Stream流
        Stream<Map.Entry<String, String>> mapEntriesStream = entries.stream();

        Integer[] integers = {1, 2, 3, 4};  //可变参数转换为Stream流
        Stream<Integer> integers1Stream = Stream.of(integers);

        String[] strings = {"a","abc","dd"};
        Stream<String> strings1Stream = Stream.of(strings);

        Stream<Integer> integerStream = Stream.of(1, 2, 3);  //数组转换为Stream对象
    }
}
/*
* 使用一个流的三个基本步骤:
*       获取一个数据源
*       数据转换
*       执行操作获取想要的结果
*
* 获取流的两种方式:
*       java.util.stream.Stream<T>是java 最常用的流接口(不是函数式接口)
*           两种方式:
*               所有Collection集合都可以通过stream默认方法获取
*                       default stream<E> stream()
*               Stream接口的静态方法of可以获取数组对应的流
*                       static<T> Stream<T> of (T……values)
*
* */
package _01_知识点总结._24_Stream流;

import java.util.ArrayList;
import java.util.stream.Stream;

public class _04_Stream流中foreach {
    public static void main(String[] args) {
        System.out.println("================================");
//        Stream<String> stringStream = Stream.of("张三","赵六","王五");

//        stringStream.forEach((name) -> {    //遍历流中的数据  forEach
//            System.out.println(name);
//        });

        System.out.println("================================");
//        Stream<String> streamFilter = stringStream.filter(name -> name.startsWith("张"));//过滤流中的数据  filter
//        streamFilter.forEach(name -> System.out.println(name));

//        System.out.println("================================");
//        Stream<String> stringStream1 = Stream.of("1", "2", "3");  //转换流中的数据类型  map方法
//        Stream<Integer> integerStream = stringStream1.map((String s) -> {
//            return Integer.parseInt(s);
//        });
//        integerStream.forEach(i -> System.out.println(i));

//        System.out.println("================================");
//        ArrayList<Integer> arrayList = new ArrayList<>();
//        arrayList.add(1);
//        arrayList.add(2);
//        arrayList.add(3);
//        arrayList.add(4);
//        Stream<Integer> stream = arrayList.stream();
//        long count = stream.count();  //统计流中的数据个数  count方法
//        System.out.println(count);

        System.out.println("================================");
        String[] array = new String[3];
        array[0] = "zhang";
        array[1] = "an";
        array[2] = "ke";
        Stream<String> array1 = Stream.of(array);
//        Stream<String> limit = array1.limit(2); //截取流中前n个的数据  limit方法
//        limit.forEach(s -> System.out.println(s));
//        Stream<String> skip = array1.skip(1);  //跳过流中前n个的数据  skip方法
//        skip.forEach(s -> System.out.println(s));

        String[] array2 = new String[3];
        array[0] = "zhang";
        array[1] = "an";
        array[2] = "ke";
        Stream<String> array3 = Stream.of(array);
        Stream<String> concat = Stream.concat(array1, array3);//连接Stream流  concat方法
        concat.forEach(s -> System.out.println(s));


    }
}
/*
* Stream流中for each方法
*       void forEach(Consumer<? super T> action);
*           注:foreach方法遍历流中的数据
*               是一个终结方法,遍历后不能再使用Stream流中其他方法
*           注:延迟方法:返回值类类型是Stream接口自身类型的方法,支持链式调用
*               终结方法:返回值类型不是Stream接口自身类型的方法,(count   forEach  除此均为延迟方法)
*       Stream管道流的特点:
*               属于管道流,只能使用一次
* */
package _01_知识点总结._24_Stream流;


import java.util.ArrayList;

/*
* 集合元素处理:
*       两个ArrayList集合,存储多个名字,
*               集合一:名字3个字,到新集合
*               集合一:筛选前2个,到新集合
*               集合二:姓张的,到新集合
*               集合二:不要前2,到新集合
*               集合一二筛选后的合并到新集合
*               根据姓名创建person对象到新集合
*               打印person集合
* */
public class _05_传统方式筛选集合案例 {
    public static void main(String[] args) {
        ArrayList<String> array1 = new ArrayList<>();
        array1.add("张三丰");
        array1.add("胡海阁");
        array1.add("罗宾和");
        array1.add("王益");
        array1.add("太祖风");
        array1.add("张婵");

        ArrayList<String> array11 = new ArrayList<>();
        for (String i : array1) {
            if(i.length()==3) {
                array11.add(i);
            }
        }

        ArrayList<String> array12 = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            array12.add(array11.get(i));
        }

        System.out.println("================================");
        ArrayList<String> array2 = new ArrayList<>();
        array2.add("张三丰");
        array2.add("胡海阁");
        array2.add("罗宾和");
        array2.add("王益");
        array2.add("太祖风");
        array2.add("张婵");
        array2.add("张无忌");

        ArrayList<String> array21 = new ArrayList<>();
        for (String s : array2) {
            if(s.startsWith("张")) {
                array21.add(s);
            }
        }

        ArrayList<String> array22 = new ArrayList<>();
        for (int i = 2; i < array21.size(); i++) {
            array22.add(array21.get(i));
        }

        ArrayList<String> array = new ArrayList<>();
        array.addAll(array12);
        array.addAll(array22);

        ArrayList<Person> arrayPerson = new ArrayList<>();
        for (String s : array) {
            arrayPerson.add(new Person(s));
        }

        for (Person person : arrayPerson) {
            System.out.println(person);
        }



    }
}
package _01_知识点总结._24_Stream流;


import java.util.ArrayList;
import java.util.stream.Stream;

/*
* 集合元素处理:
*       两个ArrayList集合,存储多个名字,
*               集合一:名字3个字,到新集合
*               集合一:筛选前2个,到新集合
*               集合二:姓张的,到新集合
*               集合二:不要前2,到新集合
*               集合一二筛选后的合并到新集合
*               根据姓名创建person对象到新集合
*               打印person集合
* */
public class _06_Stream流筛选集合案例 {
    public static void main(String[] args) {
        ArrayList<String> array1 = new ArrayList<>();
        array1.add("张三丰");
        array1.add("胡海阁");
        array1.add("罗宾和");
        array1.add("王益");
        array1.add("太祖风");
        array1.add("张婵");

        Stream<String> stream11 = array1.stream().filter(name -> name.length() == 3).limit(2);

        System.out.println("================================");
        ArrayList<String> array2 = new ArrayList<>();
        array2.add("张三丰");
        array2.add("胡海阁");
        array2.add("罗宾和");
        array2.add("王益");
        array2.add("太祖风");
        array2.add("张婵");
        array2.add("张无忌");

        Stream<String> stream22 = array2.stream().filter(name -> name.startsWith("张")).skip(2);

        Stream.concat(stream11, stream22).map(name -> new Person(name)).forEach(p -> System.out.println(p));





    }
}

_25_方法引用

package _01_知识点总结._25_方法引用;



public class _01_方法引用概述 {
    public static void printString (Printable p) {
        p.print("hello");
    }

    public static void main(String[] args) {
        printString(s -> System.out.println(s));

        printString(System.out::println);   //引用方法替代lambda表达式,两者效果相同
    }
}
/*
* 方法引用符:
*       ::  它所表达的表达式称方法引用,
*       使用条件:如果lambda要表达的函数方案已经存在于某个方法的实现中,则可以使用::来引用该方法作为lambda的替代
*       语义分析:
*               第一种:拿到参数后经lambda之手,继而传递给System.out.println方法处理
*               第二种:让System.out中println方法来取代lambda,
* */
package _01_知识点总结._25_方法引用;

public class _02_通过对象引用成员方法 {
    public static void printString (Printable p) {  //方法使用函数式接口
        p.print("heool");
    }

    public static void main(String[] args) {
//        printString((String s)-> {    //参数为函数式接口,所以可以使用lambda表达式
//            RerObject rerObject = new RerObject();
//            rerObject.method(s);   //通过对象调用引用方法
//        });

        //方法引用优化lambda表达式
        /*
        * 使用方法引用前提:
        *       对象已经存在RerObject
        *       成员方法也是已经存在的method
        *       所以可以使用对象名引用成员方法
        * */
        RerObject rerObject = new RerObject();
        printString(rerObject::method);
    }
}
package _01_知识点总结._25_方法引用;

public class _03_通过类名引用静态方法 {
    public static void printMethod(int num, Calcable c) {
        int calcable = c.calcable(num);
        System.out.println(calcable);
    }

    public static void main(String[] args) {
        printMethod(-10, (int num)->{
            return Math.abs(num);
        });

        /*
        * Math类已经存在
        * abs静态方法已经存在
        * 可以通过类名引用静态方法
        * */
        printMethod(-10,Math::abs);
    }
}
package _01_知识点总结._25_方法引用;

public class _04_通过super引用父类成员方法 {
}
package _01_知识点总结._25_方法引用;

public class _05_类的构造器 {
    public static void method (String name, BuliderName bn) {
        Person s = bn.buliderName(name);
        System.out.println(s);
    }

    public static void main(String[] args) {
        method("迪丽热巴",(String name)->{
            Person person = new Person(name);
            return person;
        });


/*
* 构造方法new Person(String name); 已知
* 对象new已知
* 使用Person引用new创建对象
* */
        method("鼓励拉闸",Person::new);
    }
}
package _01_知识点总结._25_方法引用;

public class _06_数组的构造器引用 {
    public static int[] method(int len , Array a) {
        int[] ints = a.buildArray(len);
        return ints;
    }

    public static void main(String[] args) {
        int[] array = method(10, (int l) -> {
            return new int[l];
        });
        System.out.println(array.length);
        System.out.println(
        method(11,int[]::new).length
        );
    }
}

END

posted @   老学长17300933240  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示