java基础和进阶

1.用if语句获取两个数最大值
public static void main(String[] args) {
int a = 10;
int b = 20;
int max;
if (a > b) {
max = a;
} else {
max = b;
}
System.out.println(max);
}

2.用if语句获取三个数的最大值。
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 30;
int max;
if (a > b) {
//如果a>b
if (a > c) {
//如果a>c
max = a;
} else {
//如果a<c
max = c;
}
} else {
//如果a<b
if (b > c) {
//如果b>c
max = b;
} else {
//如果b<c
max = c;
}
}
System.out.println(max);
}

3.根据变量a的值判断今天是星期几switch语句
public static void main(String[] args) {
int a = 1;
switch (a) {
case 1:
System.out.println(“星期一”);
break;
case 2:
System.out.println(“星期二”);
break;
case 3:
System.out.println(“星期三”);
break;
case 4:
System.out.println(“星期四”);
break;
case 5:
System.out.println(“星期五”);
break;
default:
System.out.println(“我们只在周一到周五工作”);
break;
}
}

4.for循环遍历1-10(遍历思想)
for (int i = 1; i < 11; i++) {
System.out.println(i);
}

5.for循环求和1-10(求和思想)
int sum = 0;
for (int i = 1; i < 11; i++) {
sum += i;
}
System.out.println(sum);

6.如何获取判断一个数是否为偶数。
if (sum%2==0) {
System.out.println(“是偶数”);
} else {
System.out.println(“是奇数”);
}

7.如何获取一个数的个位,十位,百位,千位
int ge = sum %10;
int shi = sum /10%10;
int bai = sum /10/10%10;
int qian = sum /10/10/10%10;

8,打印所有水仙花数?(水仙花数为3位数)
for (int i = 100; i < 1000; i++) {
int ge = i % 10;
int shi = i / 10 % 10;
int bai = i / 10 / 10 % 10;
if (ge * ge * ge + shi * shi * shi + bai * bai * bai == i) {
System.out.println(i + “为水仙花数”);
}
}

9.统计水仙花个数。(j计数器思想)
int count = 0;
for (int i = 100; i < 1000; i++) {
int ge = i % 10;
int shi = i / 10 % 10;
int bai = i / 10 / 10 % 10;
if (ge * ge * ge + shi * shi * shi + bai * bai * bai == i) {
System.out.println(i + “为水仙花数”);
count++;
}
}
System.out.println(“水仙花数有”+count+“个”);

10.熟练使用while死循环(配合break)
int i = 1;
while (true) {
if(i == 4){
break;
}
System.out.println(i);
i++;
}

11.打印 1-10,跳过5 (continue)
for (int i = 1; i < 11; i++) {
if(i==5){
continue;
}
System.out.println(i);
}

12.数组的定义,与取值,赋值
int[] arr = {1,2,3};
//int[] arr = new int[5];
System.out.println(arr[0]);
arr[1] = 0;

13.数组的遍历。
int[] arr = {1,2,3};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}

14.数组求和
int[] arr = { 1, 2, 3 };
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
System.out.println(sum);

15.数组取最大值。最小值自己练
int[] arr = { 1, 4, 3 };
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if(max<arr[i]){
max = arr[i];
}
}
System.out.println(max);

16.如何定义方法
public static int/返回值类型/ sum(int a, int b/形参列表 可以为空参/) {
int sum = a + b;
return sum;/返回值/ //假如方法返回值类型写的void 这里就可以不用return
}

17.方法:(有参,无参,有返回值,无返回值)
求和
数组求最值
判断传入参数是否为水仙花数

18.无参数无返回值: 定义一个方法,求出1-10的和,并在控制台上打印出来.
public static void main(String[] args) {
sumDemo();
}

public static void sumDemo(){
	int sum = 0;
	for (int i = 1; i <= 10; i++) {
		sum += i;
	}
	System.out.println("和为:"+sum);
}

19.无参数有返回值: 定义一个方法,求出1-10的和,并将其返回,在主方法中打印出来.
public static void main(String[] args) {
int sumDemo = sumDemo();
System.out.println(sumDemo);
}

public static int sumDemo(){
	int sum = 0;
	for (int i = 1; i <= 10; i++) {
		sum += i;
	}
	return sum;
}

20.有参数无返回值: 定义一个方法,求出两个int类型的数据之和,并在控制台上打印出来.
public static void main(String[] args) {
int x = 10;
int y = 20;
sumDemo(x,y);

}

public static void sumDemo(int a, int b){
	int c = a+b;
	System.out.println(c);
}

21.有参数有返回值: 定义一个方法,求出两个int类型的数据之和,并在主方法中判断他们的和是否为偶数.
public static void main(String[] args) {
int x = 10;
int y = 20;
int sumDemo = sumDemo(x,y);
if(sumDemo%2==0){
System.out.println(“偶数”);
}else{
System.out.println(“奇数”);
}
}

public static int sumDemo(int a, int b){
	int c = a+b;
	return c;
}

22.面向对象看我发的视频

23.键盘录入
//创建对象
Scanner sc = new Scanner(System.in);
//得到键盘录入的数,将他储存在a变量中
int a = sc.nextInt();
System.out.println(“键盘录入的数为:”+a);

24.键盘录入为数组赋值
int[] arr = new int[5];
for(int i = 0;i<arr.length;i++){
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
//将键盘录入的数赋值给数组当前元素
arr[i] = a;
}

25.随机数
//创建对象
Random r = new Random();
//得到随机产生的数,将他储存在a变量中
int a = r.nextInt(100); //取值范围 0-99
System.out.println(“随机产生的数为:”+a);

26.取值范围
得到 x-y 区间的数
Random r = new Random();
int a = r.nextInt(y-x+1)+x;

27.随机数为数组赋值
int[] arr = new int[5];
for(int i = 0;i<arr.length;i++){
Random r = new Random();
int a = r.nextInt(100); //取值范围 0-99
//将产生的随机数赋值给数组当前元素
arr[i] = a;
}

28.集合的定义
ArrayList list = new ArrayList();
//<>号里写什么取决去你想用集合装什么类型的数据
28.1 增 add(String s)
list.add(“第一个数据”); //向集合中添加元素

28.2 删 remove(int i)
	list.remove(i) //删除索引i所对应的元素
	
28.3 改 set(int i,String s)
	list.set(0,"哈哈") //将0号索引上面的元素改为"哈哈"
	
28.4 查 get(int i)
	String ss = list.get(i)  //获得集合中i索引所对应的元素,并用变量接受

29.集合的遍历
//通过for循环得到所有索引
for(int i = 0;i<list.size();i++){
//根据索引得到对应的元素
String s = list.get(i);
System.out.println(s);
}

30.往集合中键盘录入五个数据 (随机数版自己敲)
ArrayList list = new ArrayList<>();
for(int i = 0;i < 5;i++){
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
//将键盘录入的数添加到list集合中
list.add(a);
}

31.字符串常用API
31.1 equals() //判断两个字符串是否相等
boolean bool = s.equals(str) 判断字符串s与字符串str是否相等,返回布尔类型

31.2 equalsIgnoreCase() //判断两个字符串是否相等,忽略大小写
	
31.3 length() //得到字符串的长度
	int len = s.length() 

31.4 charAt(int index) //获得字符串中角标为index的字符
	char c = s.charAt(2) //获得字符串s中2号索引对应的字符
	
31.5 indexOf (String str) //返回指定子字符串第一次出现在该字符串内的索引
	int index = s.indexOf(str) //s中包含str,就返回str的开始位置的索引,如果不包含,就返回-1

31.6 substring(int beginIndex) //返回一个子字符串,从beginIndex开始截取字符串到字符串结尾。
	String ss = s.substring(1)  //从字符串的一号索引位置开始截取,一直截取到末尾.将截取出的内容形成新的字符串返回\

31.7 substring(int beginIndex, int endIndex) //返回一个子字符串,从beginIndex到endIndex截取字符串。含beginIndex,不含endIndex。
	String ss = s.substring(1,5) //将s的1,2,3,4号索引上的元素形成新的字符串返回

31.8 replace(CharSequence target, CharSequence replacement) //将与target匹配的字符串使用replacement字符串替换。
	String ss = s.replace("IT","it") //将字符串s中的IT替换成it,形成新的字符串返回
	
31.9 split(String regex) //将此字符串按照给定的regex(规则)拆分为字符串数组
	String[] arr = s.split("-") //将字符串s按照字符串"-"切割,将切割出来的几部分形成新的数组返回

32.Array的常用方法
32.1 toString(int[] a) //返回数组内容拼接成字符串返回。
int[] arr = {1,2,3,4};
String s = Arrays.toString(arr); //"[1,2,3,4]"

32.2 sort(int[] a) //对指定的 int 型数组按数字升序进行排序
	int[] arr = {3,4,1,2};
	Arrays.sort(arr); //[1,2,3,4]

33.Math的常用方法
33.1 abs(double a) //返回 double 值的绝对值。

33.2 floor(double a) //返回小于等于参数最大的整数 (向下取值)

33.3 ceil(double a) //返回大于等于参数的最小的整数(向上取值)

33.4 round(double a) //返回最接近参数的 long。(相当于四舍五入方法)

Object:超类,基类,根类
String toString() :输出对象在内存中的地址值和全类名–> 全类名@十六进制的地址值; 输出对象其实就是输出对象.toString();
boolean equals(Object obj) :判断的是调用方法的对象和传入的对象在内存中的地址值是否相同;
//==:判断基本数据类型的值是否相等 判断的是引用数据类型在堆内存中的地址值是否相同;
在编写事物描述类的时候需要重写toString()和equals();
事物描述类(JavaBean):
1.私有成员变量
2.生成无参构造
3.生成含参构造
4.生成getters and setters 方法
5.重写hashCode and equals 方法
6.重写toString方法
7.实现 Serializable 接口,并生成一个序列号;–>一个类的身份证号 --> 对象操作流ObjectInputStream/ObjectOutputStream

Date:操作时间的类 -->java.util.Date;
时间原点: 1970-01-01 00:00:00(格林威治时间)
构造方法:
public Date():获取时间对象,时间对象指向的时间是当前系统时间(会考虑时区问题);
public Date(long time):获取时间对象,时间对象指向的是传入的long类型的毫秒值相对于时间原点过了多久;
成员方法:
Date 类型的时间对象 —> long 类型的时间
long getTime() :获取当前时间对象相对时间原点过去了多少毫秒!
long 类型的时间—> Date 类型的时间对象
void setTime(long time) :设置当前时间对象指向的时间点, 1.清零时间(时间原点) 2.根据传入的long类型的毫秒值计算过了多长时间

SimpleDateFormat:格式化日期的类
构造方法:
public SimpleDateFormat(String pattern):根据传入的指定日期格式,构建一个SimpleDateFormat对象
日期格式:“yyyy”:年 -->四个小姨 “MM”:月 -->两个美眉 “dd”:日–>两个小弟弟 “HH”:小时 “mm”:分钟 -->两个小美眉 “ss”:秒
成员方法:
String类型的时间 --> Date类型的时间
Date parse(String time):把传入的String类型的时间转换成Date类型的时间;
//注意! String类型的时间格式要和创建SimpleDateFormat对象指定的日期格式完全一致!
Date类型的时间 --> String类型的时间
String format(Date date):把传入的Date类型的时间对象按照指定格式转换成String类型的时间对象!

Calendar:日历操作的类
构造方法:无 Calendar是一个抽象类,抽象类不可以创建对象
成员方法:
//构造一个Calendar对象
static Calendar getInstance():通过Calendar类名调用此方法生成一个日期对象,日期对象指向当前系统日期时间
//获取年,月,日,时,分,秒,星期
int get(int feild):
获取年: 日历对象.get(Calendar.YEAR);
获取月: 日历对象.get(Calendar.MONTH) + 1;//老外的1月返回的是 0
获取日: 日历对象.get(Calendar.DAY_OF_MONTH);//月中的日
获取时: 日历对象.get(Calendar.HOUR_OF_DAY);//24小时制的时
获取分: 日历对象.get(Calendar.MINUTE);//小时中的分
获取秒: 日历对象.get(Calendar.SECOND);//分中的秒
获取星期: 日历对象.get(Calendar.DAY_OF_WEEK) - 1; //老外的星期天是一个星期的第一天!
//设置年,月,日,时,分,秒,星期
void set(int field, int value):第一个参数是你要修改的日期字段(年,月,日,时,分,秒,星期),第二个参数是你要修改的值;
Calendar对象 —> Date对象
public Date getTime() :把Calender对象指向的时间转换成Date类型的对象;

System:系统操作的类:
构造方法:无 System是一个工具类,构造方法被私有了
成员方法:
static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length):复制数组
Object src:源数组 int srcPos:源数组起始复制元素索引
Object dest:目标数组 int destPos:目标数组从第几个索引开始接收 int length:复制多少个元素!
static long currentTimeMillis():获取当前系统时间相对时间原点过去了多少毫秒值(程序效率校验)
static void exit(int status):退出JVM,传入的参数是状态码 非0是异常退出

StringBuilder:用于便捷操作字符串的类
构造方法:
String类型的数据 —> StringBuilder类型的对象
public StringBuilder(String str):把传入的String类型的对象封装成StringBuilder对象
成员方法:
StringBuilder append(任意类型):拼接StringBuilder对象,返回自身对象;
StringBuilder reverse():反转StringBuilder对象中的内容,返回自身对象;

	String类型的数据  --->  StringBuilder类型的对象
		public StringBuilder(String str):把传入的String类型的对象封装成StringBuilder对象
	StringBuilder类型的对象 ---> String类型的对象
		1.sb对象 + "";
		2.sb对象.toString();
		3.String str = new String(sb对象);

包装类:在Java中所有的基本数据类型对应着包装类
byte --> Byte
short --> Short
int -->Integer
long -->Long
float --> Float
double -->Double
char -->Character
boolean -->Boolean

自动装箱和自动拆箱:
	类型间的转换:
		基本数据类型的值  --> 对应包装类的对象
			包装类类型 对象名 = 基本数据类型的值;  //自动装箱
		对应包装类的对象  --> 基本数据类型的值
			基本数据类型 变量名 = 包装类的对象;
			
String表示的值  ---->  基本数据类型的值
	static 对应的基本数据类型 parseXxxx(String 值):把传入的String类型的值,转换成相应基本数据类型的值
		-->如何调 
				对应基本数据类型 变量名 = 相应的包装类类名.parseXxx(String 值);
	
		举例:
			String str = "100";
			int num = Integer.parseInt(str);

集合特点:
长度可变,只能存储引用数据类型的元素
单列集合的根节点:
Collection–>接口
著名子类:
List: 接口 有索引,元素可重复,元素存取有序
Set:接口 无索引,元素不可以重复,元素存取无序
具体的实现类:
List下:
ArrayList:底层结构是数组的单列集合 —>首选!!
有索引,元素可重复,元素存取有序,增删慢.查询快
LinkedList:底层结构是链表的单列集合
元素可重复,元素存取有序,增删快.查询慢
Set下:
HashSet:底层结构是哈希表的单列集合 -->当使用元素不可重复的单列集合时首选!!
无索引,元素不可以重复,元素存取无序

Collection:单列集合的根节点
创建对象: 必须使用多态的形式创建对象
Collection<泛型> 集合名 = new ArrayList<泛型>();
增删改查:
增:
boolean add(Object obj):依次向集合中添加元素,返回true;
删:
boolean remove(Object obj):根据传入的元素,删除集合中的指定元素;删除成功返回true,删除失败返回false
void clear():清空集合中所有的元素
改: 没有修改元素的方法
查: 没有get()方法
int size():返回集合中的元素个数
遍历:
1.转数组 --> toArray()
把集合转成一个 Object[] 类型的数组,遍历数组既可以拿到集合中所有的元素;
2.迭代器 --> Iterator 集合对象名.iterator();
使用步骤:
1. Iterator it = 集合对象名.iterator();
2. 循环
while(it.hasNext()){//判断集合中是否有下个元素
泛型 变量名 = it.next();//接收获取到的集合元素
}
3.超级for,增强for, foreach
格式:
for(泛型 变量名 : 集合名/数组名){
//使用变量名既是使用集合中的元素
}
注意:
超级for的底层是由迭代器对象完成,不可以在超级for中 使用集合对象对集合中的元素进行增删改操作

List集合:
创建对象:必须使用多态的形式创建对象
List<泛型> 集合名 = new ArrayList<泛型>();
增删改查:
增:
boolean add(Object obj):依次向集合中添加元素,返回true;
void add(int index,E element):在指定索引位置添加元素;
删:
boolean remove(Object obj):根据传入的元素,删除集合中的指定元素;删除成功返回true,删除失败返回false
E remove(int index):根据索引来删除集合中的元素,返回被删除的元素
void clear():清空集合中所有的元素
改:
E set(int index,E element):修改指定索引位置上的元素并把被修改的元素返回
查:
E get(int index):获取指定索引位置上的元素
int size():返回集合中的元素个数
遍历:
1.具备Collection集合所有的遍历方式
2.使用普通for循环 和 get(int index)/size()配合完成
for(int i = 0;i < 集合名.size();i++){
泛型 变量名 = 集合名.get(i);
//使用集合的元素
}

迭代器:
父接口: Iterator 父接口不能对集合中的元素进行修改,所以被淘汰
子接口: ListIterator
迭代器的使用步骤:
注意:你可不可以使用Collection集合引用调用listIterator()方法? 不可以,因为Collection集合中没有listIterator();

			1创建迭代器对象
				ListIterator lit = List集合对象(List的子类集合对象).listIterator();
			2.循环获取集合中的元素
				while(lit.hasNext()){//判断集合中是否有下个元素
					泛型 变量名 = lit.next();//接收获取到的集合元素
				}
	ListIterator对象特有的功能:
		add(E e):使用迭代器对象添加元素,并立刻同步到集合中
		
底层原理:
	List集合对象(List的子类集合对象).listIterator():
		当有集合对象去创建迭代器对象的时候,在内存中会产生一个集合的副本,并有一个迭代器的游标停在集合第一个元素位置
	hasNext():判断迭代器游标右边是否有集合元素!!若有返回true,没有返回false;
	next():获取迭代器游标右边的集合元素,并移动游标到集合下一个元素位置;
	add(E element):往迭代器游标的左边添加元素并立刻同步到集合中;
	
//注意: 不可以在迭代器对象操作集合的时候,使用集合对象对集合中的元素进行增删改操作!!!!
//否则: 会有并发修改异常产生

泛型:是一种说不清楚的引用数据类型 只要看到泛型在使用时不陌生,不奇怪,不惊讶,不慌张 即可!
1.在创建集合对象时添加泛型,为了在编译阶段约束集合中元素的数据类型 -->重点
2.泛型在类的声明上: -->了解
格式:
public class 类名<泛型>{
//类的成员
}
作用:
当你在类的声明上写了泛型格式,就是假定了这个类中存在一种独特的数据类型
你可以直接在类中使用这个类型;
当你在使用有泛型约束的类时,可以自行补充具体的引用数据类型;
3.泛型在方法的声明上: -->了解
格式:
修饰符 <泛型> 返回值类型 方法名(形式参数列表){
//方法体
}
作用:
当你在方法的声明上写了泛型格式,就是在方法的内部假定了一个特殊的数据类型
你可以在方法内直接使用这个类型;
当你在调用有泛型约束的方法时,可以自行补充具体的引用数据类型;
4.泛型再接口的声明上: -->了解
格式:
public interface 接口名<泛型>{
//接口的成员
}
作用:
当你在接口的声明上写了泛型格式,就是假定了这个接口中存在一种独特的数据类型
你可以直接在接口中使用这个类型;
当你在使用有泛型约束的接口时,可以自行补充具体的引用数据类型;

泛型的好处:
	1.约束了集合中元素的数据类型  -->规范
	2.当泛型修饰类,方法,接口时   -->灵活性  -->了解

总结出现的异常:
ArrayIndexOutOfBoundsException:索引越界异常
产生原因:
访问了不存在的索引元素
解决办法:
不妨问
NullPointerException:空指针异常
产生原因:
使用值为null的对象调用了方法或者属性
解决办法:
1.不使用
2.修改该对象的值
ConcurrentModificationException:并发修改异常
产生原因:
在迭代器对象操作集合的时候,使用了集合对象对集合中的元素做了增删改操作
解决办法:
1.不使用集合对象操作集合
2.可以使用迭代器对象对集合进行增删改操作(ListIterator)
ClassCastException:类型转换异常
产生原因:
强行把一个对象转换成一个不相干类型的对象 Dog d = (Dog)arr;
解决办法:
1.不转,正确的进行转换
2.在转换之前 使用 instanceof 判断一下
例如:
if(arr instanceof Dog){
Dog d = (Dog)arr;
}
ParseException:解析异常
产生原因: 在解析数据时使用了错误的解析格式
解决办法:
使用正确的解析格式解析数据
InputMismatchException:输入不匹配异常
产生原因:
接收数据的类型和你输入数据的类型不匹配时产生
解决办法:
按照正确的类型输入数据

ArithmeticException:数学异常
	产生原因:你犯了数学错误

NoSuchElementException:没有这样的元素异常
	产生原因:
		使用迭代器对象获取集合中的下一个元素,当集合中已经没有下一个元素你还获取,就报错
	解决办法:
		使用 hasNext()提前判断一下 集合中时候还有下一个元素
		
NumberFormatException:包装类
	产生原因:
		当你使用包装类进行String类型的数字转换成相应基本数据类型的数时,传入的String类型的数据格式不对

集合特点:
长度可变,只能存储引用数据类型的元素
单列集合的根节点:
Collection–>接口
著名子类:
List: 接口 有索引,元素可重复,元素存取有序
Set:接口 无索引,元素不可以重复,元素存取无序
具体的实现类:
List下:
ArrayList:底层结构是数组的单列集合 —>首选!!
有索引,元素可重复,元素存取有序,增删慢.查询快
LinkedList:底层结构是链表的单列集合
元素可重复,元素存取有序,增删快.查询慢
Set下:
HashSet:底层结构是哈希表的单列集合 -->当使用元素不可重复的单列集合时首选!!
无索引,元素不可以重复,元素存取无序

Collection:单列集合的根节点
创建对象: 必须使用多态的形式创建对象
Collection<泛型> 集合名 = new ArrayList<泛型>();
增删改查:
增:
boolean add(Object obj):依次向集合中添加元素,返回true;
删:
boolean remove(Object obj):根据传入的元素,删除集合中的指定元素;删除成功返回true,删除失败返回false
void clear():清空集合中所有的元素
改: 没有修改元素的方法
查: 没有get()方法
int size():返回集合中的元素个数
遍历:
1.转数组 --> toArray()
把集合转成一个 Object[] 类型的数组,遍历数组既可以拿到集合中所有的元素;
2.迭代器 --> Iterator 集合对象名.iterator();
使用步骤:
1. Iterator it = 集合对象名.iterator();
2. 循环
while(it.hasNext()){//判断集合中是否有下个元素
泛型 变量名 = it.next();//接收获取到的集合元素
}
3.超级for,增强for, foreach
格式:
for(泛型 变量名 : 集合名/数组名){
//使用变量名既是使用集合中的元素
}
注意:
超级for的底层是由迭代器对象完成,不可以在超级for中 使用集合对象对集合中的元素进行增删改操作

List集合:
创建对象:必须使用多态的形式创建对象
List<泛型> 集合名 = new ArrayList<泛型>();
增删改查:
增:
boolean add(Object obj):依次向集合中添加元素,返回true;
void add(int index,E element):在指定索引位置添加元素;
删:
boolean remove(Object obj):根据传入的元素,删除集合中的指定元素;删除成功返回true,删除失败返回false
E remove(int index):根据索引来删除集合中的元素,返回被删除的元素
void clear():清空集合中所有的元素
改:
E set(int index,E element):修改指定索引位置上的元素并把被修改的元素返回
查:
E get(int index):获取指定索引位置上的元素
int size():返回集合中的元素个数
遍历:
1.具备Collection集合所有的遍历方式
2.使用普通for循环 和 get(int index)/size()配合完成
for(int i = 0;i < 集合名.size();i++){
泛型 变量名 = 集合名.get(i);
//使用集合的元素
}

迭代器:
父接口: Iterator 父接口不能对集合中的元素进行修改,所以被淘汰
子接口: ListIterator
迭代器的使用步骤:
注意:你可不可以使用Collection集合引用调用listIterator()方法? 不可以,因为Collection集合中没有listIterator();

			1创建迭代器对象
				ListIterator lit = List集合对象(List的子类集合对象).listIterator();
			2.循环获取集合中的元素
				while(lit.hasNext()){//判断集合中是否有下个元素
					泛型 变量名 = lit.next();//接收获取到的集合元素
				}
	ListIterator对象特有的功能:
		add(E e):使用迭代器对象添加元素,并立刻同步到集合中
		
底层原理:
	List集合对象(List的子类集合对象).listIterator():
		当有集合对象去创建迭代器对象的时候,在内存中会产生一个集合的副本,并有一个迭代器的游标停在集合第一个元素位置
	hasNext():判断迭代器游标右边是否有集合元素!!若有返回true,没有返回false;
	next():获取迭代器游标右边的集合元素,并移动游标到集合下一个元素位置;
	add(E element):往迭代器游标的左边添加元素并立刻同步到集合中;
	
//注意: 不可以在迭代器对象操作集合的时候,使用集合对象对集合中的元素进行增删改操作!!!!
//否则: 会有并发修改异常产生

泛型:是一种说不清楚的引用数据类型 只要看到泛型在使用时不陌生,不奇怪,不惊讶,不慌张 即可!
1.在创建集合对象时添加泛型,为了在编译阶段约束集合中元素的数据类型 -->重点
2.泛型在类的声明上: -->了解
格式:
public class 类名<泛型>{
//类的成员
}
作用:
当你在类的声明上写了泛型格式,就是假定了这个类中存在一种独特的数据类型
你可以直接在类中使用这个类型;
当你在使用有泛型约束的类时,可以自行补充具体的引用数据类型;
3.泛型在方法的声明上: -->了解
格式:
修饰符 <泛型> 返回值类型 方法名(形式参数列表){
//方法体
}
作用:
当你在方法的声明上写了泛型格式,就是在方法的内部假定了一个特殊的数据类型
你可以在方法内直接使用这个类型;
当你在调用有泛型约束的方法时,可以自行补充具体的引用数据类型;
4.泛型再接口的声明上: -->了解
格式:
public interface 接口名<泛型>{
//接口的成员
}
作用:
当你在接口的声明上写了泛型格式,就是假定了这个接口中存在一种独特的数据类型
你可以直接在接口中使用这个类型;
当你在使用有泛型约束的接口时,可以自行补充具体的引用数据类型;

泛型的好处:
	1.约束了集合中元素的数据类型  -->规范
	2.当泛型修饰类,方法,接口时   -->灵活性  -->了解

总结出现的异常:
ArrayIndexOutOfBoundsException:索引越界异常
产生原因:
访问了不存在的索引元素
解决办法:
不妨问
NullPointerException:空指针异常
产生原因:
使用值为null的对象调用了方法或者属性
解决办法:
1.不使用
2.修改该对象的值
ConcurrentModificationException:并发修改异常
产生原因:
在迭代器对象操作集合的时候,使用了集合对象对集合中的元素做了增删改操作
解决办法:
1.不使用集合对象操作集合
2.可以使用迭代器对象对集合进行增删改操作(ListIterator)
ClassCastException:类型转换异常
产生原因:
强行把一个对象转换成一个不相干类型的对象 Dog d = (Dog)arr;
解决办法:
1.不转,正确的进行转换
2.在转换之前 使用 instanceof 判断一下
例如:
if(arr instanceof Dog){
Dog d = (Dog)arr;
}
ParseException:解析异常
产生原因: 在解析数据时使用了错误的解析格式
解决办法:
使用正确的解析格式解析数据
InputMismatchException:输入不匹配异常
产生原因:
接收数据的类型和你输入数据的类型不匹配时产生
解决办法:
按照正确的类型输入数据

ArithmeticException:数学异常
	产生原因:你犯了数学错误

NoSuchElementException:没有这样的元素异常
	产生原因:
		使用迭代器对象获取集合中的下一个元素,当集合中已经没有下一个元素你还获取,就报错
	解决办法:
		使用 hasNext()提前判断一下 集合中时候还有下一个元素
		
NumberFormatException:包装类
	产生原因:
		当你使用包装类进行String类型的数字转换成相应基本数据类型的数时,传入的String类型的数据格式不对

数据结构:在一个容器中元素的存储方式;
栈结构:
先进后出,压栈弹栈–>入口出口在同一方向 弹夹
队列结构:
先进先出 -->入口出口不在同一方向 排队买包子
数组结构:
1.有索引 --> 查询快,增删慢
2.数组结构长度不可变,每一次对数组结构的容器进行增删操作都会生成一个新的容器
链表结构:
1. 分2种 单向链表 双向链表
单向链表: [地址值 元素值]
双向链表: [地址值1 元素值 地址值2]
2.查询慢,增删快
红黑树:
树结构–>根节点,根节点下有很多子节点
好处:可以根据根节点获取每个子节点,再通过子节点获取子节点下的子节点… -->treeWalk
举例:体系结构,族谱,大树,Xml,Idea中的项目结构

ArrayXxxxx:底层是数组
LinkedXxxx:底层是链表
HashXxxx:底层是哈希表
TreeXxxx:底层是红黑树

LinkedList:底层结构是链表的集合
创建对象:
LinkedList<泛型> 集合名 = new LinkedList<泛型>();
增删改查:
增:
依次添加元素:boolean add(E element)
在指定链处插入元素:void add(int index,E element)
在链表的头位置添加元素 void addFirst(E element)
在链表的尾位置添加元素 void addLast(E element)
删:
依次从头开始删除链表,返回被删除的元素:E remove()
根据元素值删:boolean remove(Object obj)
根据链表的编号删:E remove(int index)
删除头元素:E removeFirst()
删除尾元素:E removeLast()
改:
根据链表的编号来改,返回被修改的元素:E set(int index,E element)
查:
根据链表的编号来查,返回该编号的元素:E get(int index):
获取链表的头元素:E getFirst():
获取链表的尾部元素:E getLast():
遍历:
1.toArray():转数组
2.普通迭代器
3.高级迭代器 -->为了避免 并发修改异常 ConcurrentModificationException
4.普通for
5.增强for/ foreach

Set:存取无序,元素不可以重复,无索引
创建对象:一般都是直接创建具体的子类对象 HashSet
Set<泛型> 集合名 = new HashSet<泛型>();
增删改查:
增:
boolean add(E element):向集合中添加元素,若元素有重复添加失败返回false
删:
boolean remove(Object obj):删除集合中的元素,删除成功返回true,删除失败返回false
改:没有修改方法
查:没有获取单个元素的方法
boolean isEmpty():判断集合是否为空
int size():获取集合中的元素个数
遍历集合:
1.转数组
2.普通迭代器
3.超级for

关于HashSet集合存储自定义对象去重问题?
	因为add()源码 在没有重写hashCode()和equals()方法之前,比较的是集合中的元素和要添加的元素地址值是否相同;
		相同则不添加,不相同则添加
	若我设定 当一个对象的属性值完全相同的时候是同一个对象,为了解决这个问题:
		我需要在事物描述类中 要重写 hashCode()和equals() 既可以解决HashSet集合存储自定义对象去重问题!!
在JDK1.7的时候,去重逻辑依照 哈希算法
在JDK1.8的时候,去重逻辑依照 哈希算法+红黑树    红黑树只是提高了对比的效率

LinkedHashSet 和 HashSet 的区别在哪里?
	1. HashSet 是 LinkedHashSet 的父类集合;
	2. LinkedHashSet 因为加入了链表结构,LinkedHashSet在存取元素的时候从无序变成了有序
	3. 在使用的时候LinkedHashSet和HashSet 没有太大区别 (增删改查)

可变参数:
定义在哪? 形式参数位置
格式:
数据类型…变量名(数组名)
本质: 可变参数的本质其实就是一个数组
注意:
1.在调用有可变参数的方法时,在该实参位置可以传入任意个该类型的数据;
2.在可变参数的后面不可以添加其他任意类型的形式参数
3.可以在可变参数的前面添加其他形式参数

Collections:用于操作Collection接口的工具类!!
public static boolean addAll(Collection c, T… elements) :把第二个参数中的数据添加到第一个参数的集合中
public static void shuffle(List list) :随机打乱集合中元素的顺序。
public static void sort(List list) :将集合中元素按照默认规则排序。
//注意:若要使用这个方法,该集合的泛型类要实现 Comparable<泛型>,并且重写 compareTo(泛型 变量名){}
//在compareTo方法内,由自己给定一个排序规则
public static void sort(List list,Comparator<泛型>):将集合中元素按照指定规则排序
指定规则:在实参位置 创建一个Comparator<泛型>的匿名内部类,并在匿名内部类的内部重写 compare(泛型 变量名1,泛型 变量名2){}
在compare方法内,由自己给定一个排序规则

总结一下:
	只要我要使用Collections 中的sort(排序方法) 要么由源码给定排序规则,要么由自己给定排序规则;
		记住:一定要给排序的规则
		
逻辑点:
	compare(泛型 变量名1,泛型 变量名2):
		变量名1 - 变量名2  --> 升序
		变量名2 - 变量名1  --> 降序
		
Comparable和Comparator的异同之处:
	相同点:
		1.两个都是接口;
		2.两个都是用于设定排序规则的;
	不同点:
		1.Comparable 用于给 事物描述类实现的, 要使用 Collections中的一个参数的sort方法.这个事物描述类必须实现comparable接口,实现compareTo方法
			直白的说: Comparable是给事物描述类实现的!!
		2.Comparator 以匿名内部类的形式存在 Collections的两个参数的sort方法的实参位置,在匿名内部类的内部实现compare()
			直白的说: Comparator是在方法的实参上用的!!

Map<K,V>:双列集合的根接口
<K,V>:双列集合的泛型 K:键的数据类型 V:值的数据类型
特点:
1.双列集合是由一根Set集合作为键,Collection集合作为值;
2.键:元素不能重复,元素存取无序,只能由一个值为null的元素
3.值:元素可以重复
4.键和值是一对映射关系!
创建对象:
HashMap<键的泛型,值的泛型> 集合名 = new HashMap<键的泛型,值的泛型>();
增删改查:
增,改:
V put(K key,V value):向Map集合中添加映射关系;
若添加的key没有重复,添加映射关系,并返回null;
若添加的key重复,替换原有的值,返回被替换的值;
删除:
V remove(K key):根据键来删除对应的值,返回被删除的值
boolean remove(Object key,Object value):根据键和值来删除映射关系,返回删除是否成功
查:
V get(Object key):根据键来找对应的值,返回找的值
boolean containsKey(Object key):判断Map集合中是否包含传入的键
boolean containsValue(Object value):判断Map集合中是否包含传入的值
int size():返回Map集合中键值对的对数
boolean isEmpty():判断集合是否为空
Set keySet():获取集合中所有的键,并存入到Set集合中;
Collection values():获取集合中所有的值,并存到Collection集合中;
遍历:
第一种:获取集合中所有的键,通过键找值; keySet()和get(K key)配合完成
HashMap<键的泛型,值的泛型> 集合名 = new HashMap<键的泛型,值的泛型>();
Set<键的泛型> keys = 集合名.keySet();
for(键的泛型 key:keys){
值的泛型 value = 集合名.get(key);
//操作集合的键和值
}
第二种:获取集合中键值对对象;–>获取结婚证对象 entrySet()和Entry对象的getKey()和getValue()
HashMap<键的泛型,值的泛型> 集合名 = new HashMap<键的泛型,值的泛型>();
Set<Map.Entry<键的泛型,值的泛型>> entrys = 集合名.entrySet();
for(Map.Entry<键的泛型,值的泛型> entry:entrys){
键的泛型 key = entry.getKey();
值的泛型 value = entry.getValue();
//操作集合的键和值
}

LinkedHashMap和HashMap的区别:
	LinkedHashMap因为添加了链表的结构,添加的元素变成了存取有序的!!
	
Debug模式-->断点调试
	步骤:
		1.打断点:哪里不会点哪里,在行号的位置点一下出现一个红点
		2.debug运行程序-->右键 --> debug as ----
		3.在debug控制台按F7进行代码的向下执行(若不要执行到方法内部,按F8(step over))
		4.断点调试完毕后记得取消断点(在打断点的位置再次点击一下!)
	
异常的学习: -->核心
1.出现了异常 我可以怎么处理(要么try..catch要么在方法的声明上throws这个异常);
	你可以选择丢给JVM处理,不自己提供解决方案;
2.try..catch 的好处:
	try..catch 并不会影响其他代码的执行,只有try中的包裹的代码出了问题,
	从try中哪行代码开始停止运行,跳到catch中去执行你的解决方案,不会影响try..catch外的代码执行
	另一个好处:我们可以自主的提供我对该异常的解决方案!!

Java中异常的结构
根节点: Throwable
子类:
Error:错误 -->没办法解决,必须立刻修改代码
Exception:异常 -->可以解决
孙子类:
RuntimeException:运行时期异常的根节点

try…catch 语句:
1.格式
try{
可能出现问题的代码
}catch(异常的类名 e){
你解决异常的方式
}
2.执行流程:
1.代码进入try执行
2.若try中包裹的代码出现了异常,立即停止try中语句的执行,进入catch中执行你提供的解决方案;
执行完毕后,执行try…catch外的代码;
3.若try中包裹的代码没有出现异常,不会执行catch中的语句;代码从上至下正常执行
3.注意事项:
1.try…catch 不可以分开使用
2.当异常产生的时候,JVM会自动的创建一个异常对象,把这个异常对象赋值给catch括号内的形参
3.一个try可以有多个catch,但是上面catch中异常的类型大小要小于下面catch异常的类型
catch处理的异常应该由小到大依次编写
4.当我在catch中处理的是一个父类型的异常,当子类异常对象产生的时候,父类异常是可以接受子类异常对象!
所以 当我不知道要catch什么异常的时候 catch(Exception e)

异常对象的成员方法:
void printStackTrace():以红色字体打印异常类型,打印异常的错误信息,打印异常可能出现的位置
try{
//…
}catch(Exception e){
e.printStackTrace();
}

finally:一定会执行的代码
使用场景:一定是跟着try…catch一起使用,表示try…catch执行完毕后一定会执行的代码!!
格式:
try{
可能出现问题的代码
}catch(异常的类名 e){
你解决异常的方式
}finally{
一定会执行的代码;
}
注意:
1.finally中一般都写一些不得不写的内容;例如:关流等等…
2.一个try…catch中只能由一个finally

JVM处理异常的方式:
当程序出现异常,创建一个该异常类型的对象,并且立刻停止代码的执行,把该异常信息在控制台上打印出来!
1.会创建该异常类的对象
2.停止运行代码
3.打印异常信息
总结:丢给你,撂挑子

进程:正在执行的应用程序
线程:存在于正在执行的应用程序中
一个进程可以存在多个线程,进程与进程之间是没有关系的

CPU执行程序,不是在执行进程,而是执行线程,而线程与线程间是以一种 抢占式(很强的随机性) 的方式来请求cpu处理
	不同进程之间的线程都混在一起,抢着要CPU处理它!!

线程的体系结构
根接口: Runnable
根节点: Thread

创建线程的2种方式:
	1.继承方式 -->不推荐,继承的机会有限
		1.创建子类继承Thread父类
		2.重写run方法,在run方法的内部编写线程需要完成的工作
		3.在要使用线程的位置,创建该类的对象,
				并调用 start()方法启动线程,
				调用setName("线程的名称")修改线程名称
				
	2.实现方式 -->推荐方式
		1.创建子类实现Runnable接口
		2.重写run方法,在run方法的内部编写线程需要完成的工作
		3.在要使用线程的位置,创建该类的对象;
		4.再创建 Thread类型的对象  -->Thread t = new Thread(Runnable子类对象); 并把Runnable实现类的对象传入到构造方法内
			//本质上是为了做类型转换   Runnable实现类 ---> Thread类型
		5.使用线程对象 调用 start()方法启动线程,
				调用setName("线程的名称")修改线程名称
	
	以匿名内部类的方式开启线程 --->属于实现Runnable接口的方式开启线程  -->掌握
//利用匿名对象和匿名内部类配合快捷的分配线程任务和快捷启动线程
new Thread(new Runnable(){
	@Override
	public void run(){
		//线程需要执行的任务
	}
},"线程的名称").start();

同步代码块: -->掌握
synchronized(锁对象){
//需要保护的线程任务代码
}
锁对象:
1.当你只有一个任务对象的时候,锁对象可以是没有被 static 修饰的一个成员位置上的对象(任意类型);
(第一种情况下,你也可以快捷的使用 this 关键作为这个锁对象)
2.若你有多个任务对象,而锁对象需要同时监管多个线程任务的时候,你需要在锁对象的前面 加 static;

同步方法: -->了解
public synchronized void 方法名(){
//需要保护的代码
}

同步方法的锁对象: this 

同步方法可以替换 同步代码块

Lock类 -->接口 -->掌握
创建Lock类对象 —> 创建在任务类中 成员位置
Lock lock = new ReentrantLock();
上锁解锁的位置在run()方法内部
1.给线程上锁 : lock.lock(); --> 从哪里开始上锁就在哪里调这个方法
2.给线程解锁 : lock.unlock(); -->需要在哪解锁就在哪里调用这个方法

线程的状态: 站在JavaJDK的角度去看问题 -->六种 -->简单深入的了解一下
NEW --> 新建状态 线程对象刚被创建好,并没有启动(start());
RUNNABLE --> 运行状态 当线程对象正在执行run()方法中的代码的时候;
BLOCKED -->阻塞状态 一定会有同步锁参与,当一个线程对象被锁对象保护起来的时候,
其他线程对象在等待执行的状态称作阻塞状态
WAITING -->无限等待状态 当这个线程对象被其他的线程对象使用了wait()且没有被其他线程对象使用notify(),
这个过程中的状态称作无限等待状态
TIMED_WAITING -->限时等待状态 当这个线程对象被其他的线程对象使用了wait(毫秒值)/自己调用了sleep(毫秒值),
该线程进入了 限时等待状态
TERMINATED -->死亡状态 当线程对象已经执行完 run()方法中所有的代码时,该线程对象进入了 死亡状态

生产者和消费者:线程间的通讯,线程间的协作
这种设计模式的好处: 可以节约线程资源

线程池的开启方式:
1.创建线程池对象
2.创建任务对象
3.线程池对象提交任务对象
4.关闭线程池(选择不关)

	//第一步:创建线程池对象
	ExecutorService 线程池的名称 = Executors.newFixedThreadPool(num);//num: int类型 线程池中可循环使用的线程数量
	//第二步:创建任务对象
	Runnable 任务对象名 = ()->{run方法内的方法体;};
	//第三步:向线程池内的线程提交任务
	线程池的名称.submit(任务对象名);//你可以多次提交,当你的提交次数大于num 大于num的任务会等待之前的任务完成后再执行
	//第四步:关闭线程池
	线程池的名称.shutdown();

Lambda表达式:是匿名内部类的一个简单的书写方式(JDK8之后的新语法)
前提条件:接口中的抽象方法只能有一个!!(Lambda使用的范围不大)***
使用场景: 线程中的Runnable接口中的run()方法
比较器中的Comparator接口中的compare(T o1,T o2);
标准格式:在调用方法的实参位置
(抽象方法的形参列表)->{实现方法内的语句体}
简化格式:
1.当接口中的抽象方法只有一个形参的时候,可以省略形参的数据类型和小括号
形参名->{实现方法内的语句体}
2.当接口中的抽象方法有多个形参的时候,可以省略形参的数据类型(形参类型不一样也可以省略)
(形参名1,形参名2…)->{实现方法内的语句体}
3.假设接口中的抽象方法没有形参,且实现方法的语句体只有1句
可以省:方法的大括号,方法中的return可以省,方法语句的后的;也可省略
不能省:当方法是无参的,不能省小括号
()->语句体

File类:用于操作计算机中文件和文件夹的类
重要:
	相对路径: 注意! 再注意!
		Eclipse:相对Java Project的根目录
		Idea:相对Project的根目录
	绝对路径:以盘符开头的一定是绝对路径(Eclipse和Idea没区别)
		诀窍:当你不会写路径的时候,直接选择绝对路径;

构造方法:
*	File(String pathname):把指定的路径的文件或者文件夹封装成为一个File类型的对象
		//1.创建一个File对象 2.在堆内存中开辟了一个空间  3.使用File对象指向了这个计算机中的文件(文件夹)
		//注意:file对象的创建并不能决定你这个文件是文件夹还是文件,是由你使用的创建方法决定的
	File(String parent, String child) :把路径拆分为父路径和子路径,把此路径的文件或者文件夹封装成为一个File类型的对象
*	File(File parent, String child) :把路径拆分成了父路径的File对象和子路径,把此路径的文件或者文件夹封装成为一个File类型的对象
成员方法:
	获取功能的方法:
*		public?String?getAbsolutePath() :返回File对象指向的文件的绝对路径(String类型) 
		public?File?getAbsoluteFile() :返回File对象指向的文件的绝对路径(File类型) 
		public?String?getPath() :若你创建File对象时传入的是绝对路径,返回的是对象的绝对路径,
								  若你创建File对象时传入的是相对路径,返回的是对象的相对路径
*		public?String?getName() :返回由此File表示的文件或目录的名称。 
		public?long?length() :返回由此File表示的文件的大小(字节数)/若File对象指向的是文件夹,返回值是一个不确定数;
	判断功能的方法:
*		public?boolean?exists() :此File表示的文件或目录是否实际存在。 
*		public?boolean?isDirectory() :此File表示的是否为目录。 
*		public?boolean?isFile() :此File表示的是否为文件。
	创建删除功能的方法:
*		public?boolean?createNewFile() :把file对象指向的东西以文件的形式创建出来; 
*		public?boolean?delete() :把file对象指向的文件删除(不走回收站);
			//注意:若你要删除多级目录,删除文件的思路是:先删除文件夹下所有的文件,再删除文件夹
		public?boolean?mkdir() :创建由此File表示的目录。(单级) 
*		public?boolean?mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。
	遍历功能://注意:若File对象指向的是一个文件,返回值是一个 null
		public String[] list():以字符串数组的形式返回File对象指向的目录下所有的文件和文件夹;			
*		public File[] listFiles():以File数组的形式返回File对象指向的目录下所有的文件和文件夹;
*		public File[] listFiles(FileFilter ff):按照FileFilter筛选器的要求,以File数组的形式返回File对象指向的目录下满足要求的文件和文件夹;

递归:在方法的内部调用方法本身
诀窍:
1.勇敢的在方法的内部调用方法本身
2.一定要有出口
3.递归的次数不要太多 --> StackOverflowError(栈内存溢出的错误)
核心:
递归方法一定要有出口
在方法内部调用方法本身时,传入的实参一定要往 出口方向 前进!!

FileFilter:java.io.FileFilter --> 接口 -->文件选择器
1.应用场景:配合File类中 public File[] listFiles(FileFilter ff) 一并使用
2.如何使用:
1.创建FileFilter子类实现类,并在子类中重写accept(File pathname)方法,并在方法体的内部自定义筛选规则
在测试类中,使用File类型的对象调用listFiles(FileFilter ff)方法时,传入子类实现类的对象,即可按照你指定的规则对文件进行筛选;
2.在测试类中,使用File类型的对象调用listFiles(FileFilter ff)方法时,使用匿名内部类的方式,实现筛选;
3.在测试类中,使用File类型的对象调用listFiles(FileFilter ff)方法时,使用Lambda表示式的方式,实现筛选;
注意:
listFiles(FileFilter ff)方法的返回值是File[],数组中存放的是满足要求的File对象

标准代码: File[] files -->存的是满足要求的File对象
	Lambda表达式:
		File[] files = File对象.listFiles(pathname -> {
			//你的筛选逻辑
		});
		
	匿名内部类:
		File[] files = File对象.listFiles(new FileFilter(){
			@Override
			public boolean accept(File pathname){
				//你的筛选逻辑
			}
		});
	
	IO流:
I: Input    -> 输入流
O: Output	-> 输出流

IO流分类:
	按照流向分: 输出和输入流  -->参照物(Java程序)
		冷知识: 绝大多数流都是成对出现的 (既有输出流也有输入流), 
			打印流是单身汉流只有输出流没有输入流 PrintWriter(打印字符流)/PrintStream(打印字节流) --> 输出
			
			打印到控制台的  System.out -->标准的系统输出流
			输入到控制台的  System.in -->标准的系统输入流
		
	
	按操作文件类型分: 字符流和字节流
	
		字符流的本质其实就是字节流,只是对字节流的功能进行了提升,让字节流在操作字符文件的时候更加的高效!
	
IO是Java代码和现实世界连接的桥梁   
	存储:把数据保存起来
	读取:可以操作读到的数据  

编程的意义:
	1.解决生活中的问题;
	2.交互(沟通) 
		软件(代码)<->计算机  
集合:代码执行过程起到临时存储的功能;  
	若你需要永久存储数据: 硬盘!  
	
IO流也可以比作水管,当我们打开水龙头,有水出来
	水管相当于 IO流
	管中的水  IO流传输的数据
	
	洗手: 先打开水龙头, 使用水洗手  ,关闭水龙头
	IO操作: 要创建IO的对象 ,  使用对象读取(输出)数据  , 关闭资源

计算机中的文件全都是二进制文件(字节文件) --> 计算机中最小存储单位 字节B

在这些字节文件中,存在一群特例 ---> 字符文件  --> 能使用windows系统自带记事本打开的文件 称为字符文件;
	.java  .txt  .xml .html .js 


如何区分Java JDK中的流是字节流还是字符流呢?
	以Stream结尾的流  --->都叫字节流    ObjectInputStream/ObjectOutputStream
	以Writer/Reader结尾的流 -->都叫字符流   BufferedReader/BufferedWriter
	
	
	OutputStreamWriter  本质都是字符流
	InputStreamReader  本质都是字符流     把字节流转换成字符流
	
	杂流

	IO流的技巧: 死记 -->有标准代码!!   只用记一套(字节流) 走到哪都不怕

//public FileWriter(String fileName)的源码
public FileWriter(String fileName) throws IOException {
    super(new FileOutputStream(fileName));//-->创建了一个普通字节输出流对象
}

public FileOutputStream(String name) throws FileNotFoundException {
    this(name != null ? new File(name) : null, false);//--> this(第一个参数,第二个参数)
}

name != null ? new File(name) : null  
	-->若你传入的name值为null 若为null 返回null
	-->若你传入的name值不为null 返回  new File(name); -->调用File的构造方法,创建一个File对象

//public FileWriter(File file)的源码
public FileWriter(File file) throws IOException {
    super(new FileOutputStream(file));//-->创建了一个普通字节输出流对象
}

public FileOutputStream(File file) throws FileNotFoundException {
    this(file, false);//-->this(第一个参数,第二个参数)
}

file:因为你麻烦了,你帮忙创建了File类型的对象,源码就不用麻烦了

操作文本文件: 最推荐 BufferedWriter/BufferedReader -->一次一行是最快的
字符流全都是包装流!
根节点:Writer/Reader -->抽象类
普通字符流:FileWriter/FileReader
高效的字符流:BufferedWriter/BufferedReader
转换流:OutputStreamWriter/InputStreamReader
打印字符流:PrintWriter

操作任意文件: 最推荐 FileOutputStream/FileInputStream -->一次一个字节数组的方式是最快的
根节点:OutputStream/InputStream -->抽象类
普通字节流:FileOutputStream/FileInputStream
高效字节流:BufferedOutputStream/BufferedInputStream
打印字节流:PrintStream
对象操作流(序列化流):ObjectOutputStream/ObjectInputStream

要追加写:
1.在操作非字符文件,千万别追加写!!!
2.追加写的功能 一定是在 基本输出流的构造方法上 添加 true ;–>对形参 boolean append 参数进行赋值
FileWriter有, FileOutputStream有,

要设置编码格式: -->转换流有编码格式的设置,转换流构造方法的第二个参数
第二个参数:
1. String charsetName: 以字符串形式的编码名称 例如:“GBK”,“UTF-8” ****
2. Charset charSet: 以字符集对象的形式设置编码格式 -->没必要!

转换输出流有设置编码格式:
	public OutputStreamWriter(OutputStream out,String charsetName):写-->编码
转换输入流有设置编码格式:
	public InputStreamReader(InputStream in,String charsetName):读-->解码

要使用自动刷新: PrintWriter/PrintStream
在打印流的构造方法的第二个参数 boolean autoFlush 位置传 true,并且 必须使用打印对象调用 format(),println(),printf()其中之一的方法才能实现自动刷新

要自动刷新并且自动换行: **
在打印流的构造方法的第二个参数 boolean autoFlush 位置传 true
并且
必须使用打印对象调用 println()才能实现

若想把对象直接写到文件中: 序列化流
准备工作:
1.要求被序列化操作的对象的类必须实现 Serializable 接口
2.必须自动生成一个 SerialVersionUID -->类的标识
思路:化繁为简
写一次: writeObject(Object obj):
把众多的对象 放在一个集合中,把这个集合写到文件中;
读一次: readObject():
读一次,向下转型得到的是集合对象,遍历集合对象 获取集合中存储的对象们

属性集: 集合 --> 双列集合 泛型都是String
创建对象:
Properties prop = new Properties();
添加元素:
prop.put(String类型的数据,String类型的数据);
把集合中的内容加载到属性集文件里: -->使用的较少
prop.store(输出流对象);
把属性集文件中的内容加载到Properties集合内 -->使用的较多
prop.load(输入流对象);

使用原则:
	1.不知道用什么流的时候,直接字节流;			

DOS命令:
ipconfig:查看当前电脑的IP地址
我的ip:192.168.32.79
默认网关:192.168.32.1 关口,卡口 -->检查自己的网络是否通畅 xxx.xxx.xx.1
广播地址:192.168.32.255 -->群发消息 xxx.xxx.xx.255

ping 该网段下任意一个ip地址,  一般都是 ping网关

如何查看自己计算机的名称:
我的电脑 --> 右键 -->属性

1024 8080 3306

网络协议:

网络编程的三要素:  非常重要的
	IP地址:收数据的电脑的地址(收件人的地址)  注意:IP地址可以变化(虚拟IP)   
		你电脑的MAC(物理)地址 每台电脑都固定且唯一
	端口号:软件的地址  (收件人姓名 电话)   你可以随便设置 最多不要超过 5位数 注意  
			你随便写的端口号不可以和计算机中已有的端口号重复  
			非常重要的端口号: --> LocalHost:8080  MYSQL:3306
	网络协议:电脑与电脑间通讯的规则  -->快递公司
		网络协议有哪些呢?  最底层: TCP(面向连接)速度慢,安全 / UDP(面向无连接) 速度快,不安全
	
寄快递:
	你拿着你要寄的东西 到菜鸟裹裹 把 东西 给工作人员
	给你一张快递单 
	 -->快递公司  哪家快递公司接的单子,哪家负责送
		收件人的地址
		收件人姓名 电话
		
		
		
		
用时间的毫秒值对这个文件命名


一、Lambda表达式
1. 前提:必须有一个函数式接口(有且仅有一个抽象方法的接口)
2. 格式:
	标准格式:(Type1 param1,Type2 param2)->{return 语句体;}
	缺省格式:(param1,param2)->{return 语句体;}
			  (param1,param2)->语句体
			   param1->语句体

3. Lambda表示就是函数式接口的实例(理解为实现类对象)	 

在实际应用中,函数式接口一般不需要我们自己写。我们只需要使用Lambda表达式即可
练习1:使用Lambda创建一个线程,打印输出10个HelloWorld
	//使用Lambda创建一个线程,打印输出10个HelloWorld
    new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            System.out.println("Hello");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start(); 
	
练习2:写一个Student类,在集合中存储5个Student对象
	1)按照年龄对学生进行排序
	    Collections.sort(list,(o1, o2) -> o1.getAge()-o2.getAge() );
		for (Student student : list) {
			System.out.println(student.getName()+"..."+student.getAge());
		}
	2)求集合中年龄最大的学生
		//求集合中年龄最大的学生
		Student max = Collections.max(list, (o1, o2) -> o1.getAge() - o2.getAge());
		System.out.println("最大值为:"+max.getName()+"..."+max.getAge());

二、方法引用【了解】
方法的引用,是对Lambda表达式的简化写法
方法引用的格式分为下面几种
1.当Lambda表达式的语句体,是对象调用方法时,引用格式如下
对象名::方法名
2.当Lambda表达式的语句体,是调用静态方法时,引用格式如下
类名::方法名

	3.当Lambda表达式的语句体,返回一个对象时,引用格式如下
		类名::new
	4.当Lambda表达式的语句体,返回一个数组时,引用格式如下
		数据类型[]::new 

建议:Lambda已经比较简化了,方法引用在初学阶段比较影响阅读性【不建议使用】

三、常用的函数式接口
Supplier接口:
T get() 用于获取一个具体操作的结果数据

Consumer<T>接口
	accept(T t) 用于消费一个指定的数据
	Consumer<T> andThen(Consumer<T> consumer)  连续消费

Predicat<T>接口
	boolean test(T t)  用于校验指定的数据
	Predicat<T> and(Predicat<T> pre)
	Predicat<T> or(Predicat<T> pre)
	Predicat<T> negate(Predicat<T> pre)
	
Function<R,V>接口
	V apply(R r)  把数据R转换为数据V
	Function<R,V> andThen(Function<R,V> fun)  连续消费

常用的函数式接口
讲函数式接口 其实就是在说 见到了 这样的接口应用 比如用在返回值上比如用在参数列表上
实际上就是在说 这里要实现的功能是什么
而我们知道Lambda就是用来实现 具体代码的

Supplier<T>接口
   生产型 
     T get()
     可以理解为 
 Lambda表达式 表达的就是 生产(返回)一个对象
Consumer<T>接口
   消费型
    void accept(T t)
可以理解为
Lambda表达式 就是 消费(操作)一个对象

Predicate<T>接口
   条件判断接口
     就是对某种类型的数据 进行判断的
 boolean test(T t)
 可以理解为 
 Lambda表达式 就是 用来判断t对象 是不是符合某些条件

Function<T,R>接口
   转换接口
      就是将T对象变为R对象
  R apply(T t) 根据类型T 的参数 获取类型R的结果
      可以理解为
  Lambda表达式 就是用来完成T类型转换为R类型的操作方式

只出不进 Supplier
只进不出 Consumer
有进有出 Function
要是条件 Predicate

Stream 类似于 生产流水线
特点 理解为 管道
1:流水线作业
2:内遍历

对一列元素进行操作的
想使用
1:获取流
2:拼接模型
3:按照要求得到结果

流的来源
集合 数组 转换为Stream流

将Stream中数据 收集到集合或者数组中

Stream 中的方法

延迟方法
Stream filter(Predicate p) 通过该方法 将一个流转换成另一个子集流
参数是一个函数式接口 使用Lambda表达式 表达式完成的事情就是条件判断

 Stream<T> limit(long n) 对流进行截取 只取前n个 
             
 Stream<T> skip(long n) 跳过前n个元素  截取一个新流

 <R> Stream<R> map(Function<T,R> lambda)  需要将流中元素 映射到另一个流中 使用map方法
                  参数是一个函数式接口  可以将当前流中的T类型数据 转换为R类型 的流
                  Lambda中就是完成转换功能的  

终结方法
long count() 获取流中的个数 但是这个功能做完 该流程结束
forEach(Consumer lambda) 逐一遍历
参数是函数式接口 会将每一个流元素交给该函数进行处理 交给Lambda表达式

静态方法
of(…) 添加数据 形成一个管道
static Stream concat(Stream a,Stream b)
合并流

收集方法
将我们的 流 转换成 List集合
collect(Collectors.toList())
转换成Set集合
collect(Collectors.toSet())

  Object[] toArray()
  转换成指定数组
   T[] toArray(len->new T[len])

获取流
Collection stream()方法

Stream 不是集合元素 JDK8中的一个新特性 被我们称为 流

 也不是数据结构 不保存数据 它是有关算法和计算操作的 更像高级别版本的迭代器
 Stream 单向 不可往复  数据只能遍历一次 就好比流水 从前面流过了 一去不复返

 不同的地方在于 支持并行化操作 
     
 串行方式
    一个一个依次执行  

    并行 并发
    在一个时间段内 多个操作并发的执行
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值