_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接口的特点:
* 有序的集合,存取顺序一致,存123 取123
* 有索引,包含一些带索引的方法
* 允许存储重复的元素
*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

00_java进阶笔记的更多相关文章

  1. Angularjs进阶笔记(2)-自定义指令中的数据绑定

    有关自定义指令的scope参数,网上很多文章都在讲这3种绑定方式实现的效果是什么,但几乎没有人讲到底怎么使用,本篇希望聊聊到底怎么用这个话题. 一. 自定义指令 自定义指令,是Angularjs用来实 ...

  2. javascript进阶笔记(2)

    js是一门函数式语言,因为js的强大威力依赖于是否将其作为函数式语言进行使用.在js中,我们通常要大量使用函数式编程风格.函数式编程专注于:少而精.通常无副作用.将函数作为程序代码的基础构件块. 在函 ...

  3. Android进阶笔记:Messenger源码详解

    Messenger可以理解为一个是用于发送消息的一个类用法也很多,这里主要分析一下再跨进程的情况下Messenger的实现流程与源码分析.相信结合前面两篇关于aidl解析文章能够更好的对aidl有一个 ...

  4. Android进阶笔记:AIDL内部实现详解 (二)

    接着上一篇分析的aidl的流程解析.知道了aidl主要就是利用Ibinder来实现跨进程通信的.既然是通过对Binder各种方法的封装,那也可以不使用aidl自己通过Binder来实现跨进程通讯.那么 ...

  5. javascript进阶笔记(1)

    学习js已经有一段时间了,大大小小还是能够做出一些东西来.不过觉得可惜的是,还是对js本身这门语言不是很熟悉,总有一点雾里看花的感觉,看得见,但是看不清楚.最近发现有一本关于js的叫做<忍者秘籍 ...

  6. object - c 语言基础 进阶笔记 随笔笔记

    重点知识Engadget(瘾科技)StackOverFlow(栈溢出)Code4Apprespon魏先宇的程序人生第一周快捷键: Alt+上方向键 跳到最上面  Alt+下方向键 跳到最下面      ...

  7. python进阶笔记 thread 和 threading模块学习

    Python通过两个标准库thread和threading提供对线程的支持.thread提供了低级别的.原始的线程以及一个简单的锁.threading基于Java的线程模型设计.锁(Lock)和条件变 ...

  8. Android进阶笔记20:Android手机屏幕坐标系

    1. 手机屏幕坐标系: 整个坐标系是以手机屏幕左上角为原点(0,0),如下:

  9. Android进阶笔记19:onInterceptTouchEvent、onTouchEvent与onTouch

    1.onTouch方法:onTouch方法是View的 OnTouchListener借口中定义的方法,处理View及其子类被touch是的事件处理.当一个View绑定了OnTouchLister后, ...

  10. Android进阶笔记18:选用合适的IPC方式

    1. 相信大家都知道Android进程间通信方式很多,比如AIDL.Messenger等等,接下来我就总结一下这些IPC方式优缺点. 2. IPC方式的优缺点和适用场景 3. 附加:使用Intent实 ...

随机推荐

  1. Nodejs报错记录

    ◉ digital envelope routines::unsupported D:\workspace\vuedemo> npm run dev ... error:0308010C:dig ...

  2. 蚂蚁感冒【第五届蓝桥杯省赛C++A/B组】

    蚂蚁感冒 长 \(100\) 厘米的细长直杆子上有 \(n\) 只蚂蚁. 它们的头有的朝左,有的朝右. 每只蚂蚁都只能沿着杆子向前爬,速度是 1 厘米/秒. 当两只蚂蚁碰面时,它们会同时掉头往相反的方 ...

  3. 洛谷 P1208混合牛奶 题解

    一道贪心算法不是很明显的题目,其实一般的递推也可以做. 大体思路:肯定优先购买单价最低的奶农的牛奶,那么就需要先根据牛奶单价进行排序,这里用结构体会更好一点.之后在从前往后一个一个枚举,直至购买的牛奶 ...

  4. nodejs 升级后, vue+webpack 项目 node-sass 报错的解决方法

    1.npm i node-sass -D 在错误提示里有给出了方案,重新构建 node-sass,命令如下: npm rebuild node-sass --force 如果执行完成后不报错,就可以了 ...

  5. 五种传统IO模型

    五种传统I/O模型 作者:tsing 本文地址:https://www.cnblogs.com/TssiNG-Z/p/17089759.html 简介 提起I/O模型, 就会说到同步/异步/阻塞/非阻 ...

  6. drf-day1——web应用模式、API接口、接口测试工具postman

    目录 学习资料 一.web 应用模式 二.API接口 API概念 三.接口测试工具postman postman介绍 postman下载与使用 四.如何在浏览器中测试 学习资料 # 个人博客:http ...

  7. 【译】使用 ML.NET 进行机器学习 - 集群完整指南

    原文 | Nikola M. Zivkovic 翻译 | 郑子铭 在之前的几篇文章中,我们探索了一些基本的机器学习算法.到目前为止,我们介绍了一些简单的回归算法,分类 算法.我们使用 ML.NET 实 ...

  8. JAVA虚拟机20-基于栈的解释器执行过程示例

    1.准备代码 public int calc() { int a = 100; int b = 200; int c = 300; return (a + b) * c; } 2.使用javap -v ...

  9. 【CTO变形记】高维视角,跳出“农场主与火鸡”

    前言:看待人事物的角度决定了我们的思考方向和处理事情的方式.在这些认识人事物的过程中,导致了一些"事故"发生:就好比"以手指月",原本要看"月亮&qu ...

  10. elasticsearch之日期类型有点怪

    一.Date类型简介 elasticsearch通过JSON格式来承载数据的,而JSON中是没有Date对应的数据类型的,但是elasticsearch可以通过以下三种方式处理JSON承载的Date数 ...