java基础知识总结(11-15)

一、day11—API1

1、API

​ 概述
​ API:Application Programming Interface应用编程接口,一切可以调用的东西都是API。
​ --java.lang.* 包,里面都是常用的工具类
​ --重要研究几个工具类:Object / String /StringBuilder StringBuffer / Date …

2、Object

​ --1,概述
​ 类 Object 是类层次结构的根类。每个类都使用 Object 作为超类
​ --2,创建对象
​ Object()
​ --3,常用方法
​ int hashCode()
​ 返回该对象的哈希码值。
​ String toString()
​ 返回该对象的字符串表示。
​ boolean equals(Object obj)
​ 指示其他某个对象是否与此对象“相等”。

​ --测试:

//测试 Object工具类
		public class Test1_Object {
			public static void main(String[] args) {
				//1,创建Object对象
				Object o = new Object();//触发无参构造
				
				//2,调用常用方法
				//366712642,o对象在内存中的哈希码值
				System.out.println( o.hashCode() );
				
				//java.lang.Object@15db9742,展示对象在内存中的地址值
				System.out.println( o.toString() );
		//		System.out.println(Integer.toHexString(366712642));
				
				//false,比较o对象和"jack"是否相等
				System.out.println( o.equals("jack") );
			}
		}
//测试 Object工具类
		//总结
		//1,Object是所有类的 超类/父类/基类
		//2,toString()--用来展示对象的字符串--重写前展示地址值--重写后展示属性值
		//3,equals()--比较两个对象是否相等--重写前比地址值--重写后比属性值
		//4,工具提供的快捷方式--source--toString()--equals()...
		public class Test2_Object2 {
			public static void main(String[] args) {
				Student s = new Student("渣渣辉",40);//触发了含参构造
				//使用了Object父类的,展示了哈希码值-366712642
				System.out.println( s.hashCode() );
				
				//使用了Object父类的,展示了地址值-cn.tedu.api.Student@15db9742
				System.out.println( s.toString() );
				//查看属性的值
				System.out.println( s.getName() );
				System.out.println( s.getAge() );
				
				//1,想要的是,直接输出s就看到s对象的属性值?
				//但是,输出的是地址值,cn.tedu.api.Student@15db9742
				//原因:在打印对象时,会调用了toString(),自己没提供,
				//才去找到了Object提供的,默认就是要打印一个地址值.
				//想要打印属性值,--需要提供重写的toString()
				//到底打印什么数据?-重写前,打印地址值.重写后,打印属性值
				//cn.tedu.api.Student@15db9742  ->   Student [name=渣渣辉, age=40]
				System.out.println(s);
				
				Student s1 = new Student("jack",20);
				Student s2 = new Student("jack",20);
			//3,equals()--比较对象是否相同,相同就返回true,不同就返回false
		//比较s1和s2相同吗--使用了Object提供的equals(),本来就是比较对象间的地址值
				//== 比较基本类型的变量时,比较的是值本身 ,如:1==2 false  1==1 true
				//== 比较 引用类型的变量时,比较的是地址值
				//需求:进行比较时,不想比较地址值,而是比较属性值,--重写equals()
				//如果所有属性都一样,那么就认为是相同的对象,equals返回true
			//equals()到底比较什么呢?--重写前,比的是地址值,重写后,比的是属性值
				System.out.println(  s1.equals(s2)  );
				//重写前是false,因为地址值不同 -> 重写后是true,因为属性值相同
			}
		}
		class Student{//省略了 extends Object
			//构造方法--方便外界new
			public Student() { }
			public Student(String name, int age) {
				super();//调用父类Object 的无参构造
				this.name = name;
				this.age = age;
			}
			
			private String name ;
			private int age ;
			
			//get()/set()--source
			public String getName() {
				return name;
			}
			public void setName(String name) {
				this.name = name;
			}
			public int getAge() {
				return age;
			}
			public void setAge(int age) {
				this.age = age;
			}
			//2,重写toString()--目的是不再展示地址值,而是要想展示属性值
			//source -- generate toString()...ok
			@Override
			public String toString() {
				return "Student [name=" + name + ", age=" + age + "]";
			}
			//4,重写equals()--目的是比较的不再是两个对象间的地址值,而是属性值
			//source -- generate hashCode() and equals()...ok
			@Override
			public boolean equals(Object obj) {
				if (this == obj)
					return true;
				if (obj == null)
					return false;
				if (getClass() != obj.getClass())
					return false;
				Student other = (Student) obj;
				if (age != other.age)
					return false;
				if (name == null) {
					if (other.name != null)
						return false;
				} else if (!name.equals(other.name))
					return false;
				return true;
			}
			
		//	@Override
		//	public boolean equals(Object obj) {
		//		//统一类型,是学生类型再比较
		//		Student s = (Student)obj ;
		//		//判断,如果每个属性都一样,就认为是同一个对象,让equals()返回true
		//		if(this.name==s.name  && this.age==s.age) {
		//			return true ;
		//		}
		//		return false;
		//	}
		}
3、String

–1,概述
String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。
字符串是常量;它们的值在创建之后不能更改。是一个封装char[]数组的对象

–2,特点
–源码摘抄:
–public final class String --不能被继承
–private final char value[];–字符串是常量

​ 1、 如果是第一次使用字符串,java会在字符串常量池创建一个对象。

​ 2、 再次使用相同的内容时,会直接访问常量池中存在的对象。img

–3,创建对象
String(char[] value)
–4,常用方法

		char charAt(int index) 
		        返回指定索引处的 char 值。 
		String concat(String str) 
		        将指定字符串连接到此字符串的结尾。 
		boolean endsWith(String suffix) 
		        测试此字符串是否以指定的后缀结束。 
		boolean equals(Object anObject) 
		        将此字符串与指定的对象比较。 
		byte[] getBytes()  
		int hashCode() 
		        返回此字符串的哈希码。 
		int indexOf(String str) 
		        返回指定子字符串在此字符串中第一次出现处的索引 
		int lastIndexOf(String str) 
		          返回指定子字符串在此字符串中最右边出现处的索引。 
		boolean isEmpty() 
		          当且仅当 length() 为 0 时返回 true。 
		int length() 
		          返回此字符串的长度。 
		String replace(char oldChar, char newChar) 
		          返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 
		String[] split(String regex) 
		          根据给定正则表达式的匹配拆分此字符串。 
		boolean startsWith(String prefix) 
		          测试此字符串是否以指定的前缀开始。 
		String substring(int beginIndex) 
		          返回一个新的字符串,它是此字符串的一个子字符串。 
		String substring(int beginIndex, int endIndex) 
		          返回一个新字符串,它是此字符串的一个子字符串。 
		char[] toCharArray() 
		          将此字符串转换为一个新的字符数组。 
		String toLowerCase()  
		String toUpperCase()  
		String trim() 
		          返回字符串的副本,忽略前导空白和尾部空白。 
		static String valueOf(int i) 
		          返回 int 参数的字符串表示形式。 
4、StringBuilder/StringBuffer

1、 封装了char[]数组

2、 是可变的字符序列

3、 提供了一组可以对字符内容修改的方法

4、 常用append()来代替字符串做字符串连接

5、 内部字符数组默认初始容量是16:initial capacity of 16 characters

6、 如果大于16会尝试将扩容,新数组大小原来的变成2倍+2,容量如果还不够,直接扩充到需要的容量大小。int newCapacity = value.length * 2 + 2;

7、 StringBuffer 1.0出道线程安全,StringBuilder1.5出道线程不安全

public class Test4_StringBuilder {
			public static void main(String[] args) {
		//		method();//+拼接
				method2();//StringBuilder拼接
			}
			public static void method2() {
				//把指定的字符串拼接10000次
				String s = "abcdefghijklmnopqrstuvwxyz" ;
		//		StringBuilder sb = new StringBuilder();
				StringBuffer sb = new StringBuffer();
				
				long start = System.currentTimeMillis();//计时开始
				for (int i = 0; i < 10000; i++) {
					sb.append(s) ;//工具拼接
				}
				long end = System.currentTimeMillis();//计时结束
				
				System.out.println(end-start);//1ms
			}
			//+拼接
			public static void method() {
				//把指定的字符串拼接10000次
				String s = "abcdefghijklmnopqrstuvwxyz" ;
				String res = "" ;//定义变量,记录结果
				
				long start = System.currentTimeMillis();//计时开始
				for (int i = 0; i < 10000; i++) {
					res = res + s ;//+拼接慢
				}
				long end = System.currentTimeMillis();//计时结束
				
				System.out.println(end-start);//1372ms
			}
		}

二、day12—IO 1

1、包装类

–1,概述
为对应的基本类型,提供丰富的功能
–基本类型 byte short int long float double char boolean
–包装类型 Byte Short Integer Long Float Double Character Boolean

img

–2,Number类
–是所有数字类型 包装类的父类,被修饰成了抽象类,不能new
–提供的共性方法 --是可以把包装类型转回成基本类型
byte byteValue()
以 byte 形式返回指定的数值。
abstract double doubleValue()
以 double 形式返回指定的数值。
abstract float floatValue()
以 float 形式返回指定的数值。
abstract int intValue()
以 int 形式返回指定的数值。
abstract long longValue()
以 long 形式返回指定的数值。
short shortValue()
以 short 形式返回指定的数值。
–3,Integer类
–概述
包装了一个基本类型 int 的值
–创建对象
Integer(int value)
构造一个新分配的 Integer 对象,它表示指定的 int 值。
static Integer valueOf(int i)
返回一个表示指定的 int 值的 Integer 实例。
–常用方法
static int parseInt(String s)
将字符串参数作为有符号的十进制整数进行解析。
int intValue()
以 int 类型返回该 Integer 的值。
–测试

//测试 包装类
			//总结
			//1,包装类的作用,为对应的基本类型,提供丰富的方法
			//2,自动装箱: 把基本类型 包装 成包装成包装类型
			//3,自动装箱: 把包装类型 包着的是啥给拆出来,变回成 基本类型
			//4,自动装箱有两种方式:构造方法创建对象 + 静态方法创建对象(高效,推荐)
			public class Test1_Number {
				public static void main(String[] args) {
			//1,创建对象--把基本类型的5 变成 包装类型 i i2--为了用包装类丰富的方法
					Integer i = new Integer(5);//触发含参构造Integer(int value) 
					
					//整数类型高效--相同数据不再开辟空间存储--范围:-128~127
					Integer i2 = Integer.valueOf(5) ;
					Integer i3 = Integer.valueOf(5) ;
					System.out.println(i2 == i3);//i3就使用了已经存在的数据
					
					
					//2,调用方法
					int a = i.intValue();//把包装类型 包着的值 取出来--用于运算--自动拆箱
					System.out.println(a);
					//把字符串类型的数字 转成 基本类型的数字
					int b = Integer.parseInt("123");
					System.out.println(b+1);
				
					//double<->Double
					//自动装箱--把基本类型的 变成 包装类型
					Double  d = new Double(1.1) ;//double->Double  --包起来--自动装箱
					Double d2 = Double.valueOf(1.1);
					
					//自动拆箱--把包装类型 包的值拆出来 基本类型
					double m = d.doubleValue() ;//double<-Double  --拆出来--自动拆箱
					System.out.println(m);
					double n = Double.parseDouble("1.1");
					System.out.println(n+1);
				}
			}
2、Date

–1,概述
对于日期进行各种操作
–2,创建对象
Date()
分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒)。
–3,常用方法
int getDate()
已过时。 从 JDK 1.1 开始,由 Calendar.get(Calendar.DAY_OF_MONTH) 取代。
int getDay()
已过时。 从 JDK 1.1 开始,由 Calendar.get(Calendar.DAY_OF_WEEK) 取代。
int getHours()
已过时。 从 JDK 1.1 开始,由 Calendar.get(Calendar.HOUR_OF_DAY) 取代。
int getMinutes()
已过时。 从 JDK 1.1 开始,由 Calendar.get(Calendar.MINUTE) 取代。
int getMonth()
已过时。 从 JDK 1.1 开始,由 Calendar.get(Calendar.MONTH) 取代。
int getSeconds()
已过时。 从 JDK 1.1 开始,由 Calendar.get(Calendar.SECOND) 取代。
long getTime()
返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
int getTimezoneOffset()
已过时。 从 JDK 1.1 开始,由 -(Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000) 取代。
int getYear()
已过时。 从 JDK 1.1 开始,由 Calendar.get(Calendar.YEAR) - 1900 取代。

–4,测试

//测试  日期工具类
		public class Test2_Date {
			public static void main(String[] args) {
				//1,创建Date对象
				Date date = new Date();
				
				//TODO  2,调用方法
				System.out.println(  date.getDate()  );//今天是多少号
				System.out.println(  date.getDay()  );//今天是星期几
				System.out.println(  date.getHours()  );//现在是几点
				System.out.println(  date.getMinutes() );//现在是多少分钟
				System.out.println(  date.getMonth()  );//TODO 现在是几月????  
				System.out.println(  date.getSeconds()  );//现在是多少秒
				System.out.println(  date.getTime()  );//从1970.1.1 零点到现在的毫秒值
				System.out.println(  date.getYear()  );//从1900年到现在是多少年
				System.out.println(  date.toLocaleString()  );//2020-8-15 11:53:50
				
			}
		}
3、日期工具SimpleDateForma

–1,概述
专门用来把日期数据进行转化.把 String类型的日期 和 Date类型的日期 互转
–2,创建对象
SimpleDateFormat(String pattern)
用给定的模式和默认语言环境的日期格式符号构造
–3,常用方法
String format(Date date)
将给定的 Date 格式化为日期/时间字符串,变成String。
Date parse(String text)
解析字符串的文本,生成 Date。
–4,测试

import java.text.ParseException;
		import java.text.SimpleDateFormat;
		import java.util.Date;
		import java.util.Scanner;
		//测试 日期格式化的工具类SimpleDateFormat --  Date<->String
		public class Test3_SimpleDF {
			public static void main(String[] args) throws Exception { 
				//1,创建对象--参数是日期的格式 年y-月M-日d  月/日/年  
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				//2,常用方法
		//		Date date = new Date();
		//		String str = sdf.format(date) ;
				String str = sdf.format(new Date());//Date->String
				System.out.println(str);//2020-08-15
				Date d = sdf.parse("2020-08-15");//String->Date
				System.out.println(d.getMonth());
				
				//3,计算存活天数
				//接收输入的出生日期
				String birthday = new Scanner(System.in).nextLine();
				//String->Date
				Date birth = sdf.parse(birthday);
				
				//计算天数
				long start = birth.getTime() ;//出生日期 对应的毫秒值
				long now = System.currentTimeMillis() ;//当前时间的毫秒值
				
				System.out.println( (now-start)/1000/60/60/24 );//ms->天
				
			}
		}
4、BigDecimal/BigInteger

–1,概述
–BigDecimal专门用来解决 浮点数运算不精确的问题
–BigInteger专门用来解决 大型的整数运算
–2,BigDecimal创建对象
BigDecimal(double val)
将 double 转换为 BigDecimal,后者是 double 的二进制浮点值准确的十进制表示形式。
BigDecimal(String val)
将 BigDecimal 的字符串表示形式转换为 BigDecimal。
–3,常用方法
加法: BigDecimal add(BigDecimal augend)
减法: BigDecimal subtract(BigDecimal subtrahend)
乘法: BigDecimal multiply(BigDecimal multiplicand)
除法: BigDecimal divide(BigDecimal divisor)
–4,测试

import java.math.BigDecimal;
		import java.util.Scanner;
		//测试  小数运算精确的解决方案
		public class Test4_BigDecimal {
			public static void main(String[] args) {
		//		method();//暴露问题
				method2();//解决方案
			}
			public static void method2() {
				//接收输入的两个小数
				double a = new Scanner(System.in).nextDouble();
				double b = new Scanner(System.in).nextDouble();
				
				//创建对象
				//含参构造BigDecimal(double val)--有坑 
		//		BigDecimal bd1 = new BigDecimal(a);
		//		BigDecimal bd2 = new BigDecimal(b); 
				
				//触发含参构造BigDecimal(String val) -- 推荐
				BigDecimal bd1 = new BigDecimal( String.valueOf(a) );//double->String
				BigDecimal bd2 = new BigDecimal(b+"");//double->String
				
				BigDecimal bd3 = bd1.add(bd2);//加法
				System.out.println(bd3);
				
				bd3 = bd1.subtract(bd2);//减法
				System.out.println(bd3);
				
				bd3 = bd1.multiply(bd2);//乘法
				System.out.println(bd3);
				
				//除法--除不尽时--java.lang.ArithmeticException
		//		bd3 = bd1.divide(bd2);
		//重载的divide(x,y,z)-x是要参与运算的对象名称,y是保留的小数位数,z是舍入模式
				bd3 = bd1.divide(bd2,5,BigDecimal.ROUND_HALF_UP);
				System.out.println(bd3);
			}
			//暴露问题
			public static void method() {
				//接收输入的两个小数
				double a = new Scanner(System.in).nextDouble();
				double b = new Scanner(System.in).nextDouble();
				
				//做运算java
				System.out.println(a+b);//不精确
				System.out.println(a-b);//不精确
				System.out.println(a*b);//不精确
				System.out.println(a/b);//不精确
			}
		}
5、IO

–1,概述
–主要是把 程序中的数据 和磁盘里的数据 进行交互
–in/I :从磁盘里读取到程序里
–out/O : 从程序里写出到磁盘中
–无论进行读in还是写out,都可以用字节流和字符流完成
–到底用哪种流读写呢?–根据操作数据的单位不同.jpg .txt .mp4??
–字符流 只能操作字符文件.txt
–字节流 可以操作任何数据 – 应用的更加广泛

img

–2,工具类
–File:专门操作文件的工具类
–字节流–读
InputStream – FileInputStream – BufferedInputStream
–字节流–写
OutputStream – FileOutputStream – BufferedOutputStream

6、File

–1,概述
文件和目录路径名的抽象表示形式。
–2,创建对象
File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
–3,常用方法
略,同网页版笔记
–4,测试

import java.io.File;
		import java.io.IOException;
		import java.util.Arrays;
		import java.util.Scanner;
		// 测试  File工具类
		public class Test5_File {
			public static void main(String[] args) throws IOException {
				//1,新建File对象--参数是一个路径
				File file = new File("D:\\iotest\\1.txt");
				
				//2,调用方法
				System.out.println(  file.length() );//获取文件的字节量
				System.out.println(  file.exists() );//判断文件是否存在
				System.out.println(  file.isFile() );//判断是不是文件
				System.out.println(  file.isDirectory() );//判断是不是文件夹
				System.out.println(  file.getName() );//获取文件名
				System.out.println(  file.getParent() );//获取父路径
				System.out.println(  file.getAbsolutePath() );//获取完整路径
				
				file = new File("D:\\iotest\\2.txt");
				System.out.println(  file.createNewFile() );//新建文件
				
				file = new File("D:\\iotest\\xyz");
				System.out.println(  file.mkdir() );//新建一层不存在的文件夹
				
				file = new File("D:\\iotest\\a");
				System.out.println(  file.mkdirs() );//新建多层不存在的文件夹
				
				file = new File("D:\\iotest\\2.txt");
				System.out.println(  file.delete() );//删除文件 或者 空的文件夹
				
				//列出文件夹里的资源
				file = new File("D:\\iotest");
				String[] strs = file.list();//获取资源名称,放入String[]
				System.out.println(  Arrays.toString(strs) );
				
				//获取到资源,并把资源一个一个的封装成File对象存入File[]--推荐
				File[] fs = file.listFiles();
				System.out.println(  Arrays.toString(fs) );
				
				//TODO 练习:
				//接收用户输入的文件夹路径
				String path = new Scanner(System.in).nextLine();
				File f = new File(path) ;//把路径封装成File对象
				
				//列出文件夹里的所有资源
				File[] a = f.listFiles() ;
				
				long sum = 0 ;//定义变量,记录文件的总大小
				//遍历数组,获取每个资源
				for(int i = 0 ; i < a.length ;i++) {
					
					//判断,拿到的资源是文件吗? -- a[i]
					if( a[i].isDirectory() ) {//如果是文件夹
						System.out.println("这是一个文件夹,文件夹名字是:"+a[i].getName());
					}else if( a[i].isFile() ) {//如果是文件
						sum = sum + a[i].length() ;//求所有文件的总大小
					}
				}
				
				System.out.println("文件总大小是:"+sum);
			}
		}

7、常见字符编码表
编码说明编码范围字节量
ASC-II英文,标点,基本指令0到127单字节
ISO-8859-1ASC-II扩展,西欧字符128到255单字节
ANSI,CJKANSI是一种字符编码规范,设计为了使计算机支持更多语言,英文用单字节编码,其他字符用双字节编码CJK表示亚洲字符编码的统称(中日韩)
GBK中国国标码最大65535英文使用单字节,中文使用双字节
UNICODE统一码Java的char类型字符 就采用Unicode编码100万+编码位,分为常用字符表,生僻字符表等,我们只是用常用表常用字符表所有字符都采用双字节
UTF-8Unicode传输格式Unicode Transformations Format为了解决Unicode英文字符字节量翻倍的问题,提出的一种变长的编码格式英文单字节某些字符双字节中文三字节一些特殊符号四字节
public void code() throws IOException {
       String s = "我爱你中国";
       System.out.println(s.getBytes("utf-8").length);//15--unicode/u8一个汉字3字节存储
       System.out.println(s.getBytes("gbk").length);//10--中文双字节
       System.out.println(s.getBytes("unicode").length);//12--双字节+2
       System.out.println(s.getBytes("iso-8859-1").length);//5--单字节
    }

三、day13—IO 2

1、递归

​ --1,概述
​ 就是在方法里,调用自己.
​ --2,练习
​ --递归求目录总大小
​ package cn.tedu.io;

		import java.io.File;
		import java.util.Scanner;

		//测试 递归求目录总大小
		/*
		 * 1,列出文件夹里的所有资源
		 * 2,拿到每个资源进行判断
		 * 3,如果是文件,直接.length求和
		 * 4,如果是文件夹呢?
		 * 		---继续列表继续判断是文件就求和是文件夹继续再列表再判断再求和
		 * 		---开始重复的干活,干的是1 2 3 的活
		 */
		public class Test1_Digui {
			public static void main(String[] args) {
				System.out.println("请输入文件夹路径:");
				String path = new Scanner(System.in).nextLine();
				//把路径封装成File对象->为了用File工具类的各种方法
				File dir = new File(path);
				
				//调用方法,求大小
				long size = sizeOf(dir);
				System.out.println(size);
			}
			//创建sizeOf(),求大小
			public static long sizeOf(File file){
		//		1,列出文件夹里的所有资源
				File[] fs = file.listFiles() ;
				
				long max = 0 ;//定义变量,记录总和
				
		//		2,遍历数组,拿到每个资源fs[i]进行判断
				for(int i = 0 ; i < fs.length ; i++) {
					if(fs[i].isFile()) {
		//		3,如果是文件,直接.length求和
						max = max + fs[i].length() ;
					}else if( fs[i].isDirectory() ) {
		//		4,如果是文件夹呢?--发生递归
		//			---继续列表继续判断是文件就求和是文件夹继续再列表再判断再求和
		//			---开始重复的干活,干的是1 2 3 的活
						max = max + sizeOf( fs[i] ) ;
					}
				}
				return max ;//把max的值返回给调用位置
			}
			
		}

遍历目录,列出层级关系

public class Test_File3 {
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		String path = s.nextLine();
		File f = new File(path);
		printfFile(f,0);
	}
	public static void printfFile(File file,int level) {
		//输出层级
		for(int i=0;i<level;i++) {
			System.out.print("-");
		}
		
		//输出文件名
		System.out.println(file.getName());
		
		//如果是文件夹
		if(file.isDirectory()) {
			File[] f = file.listFiles();
			for(File temp: f) {
				printfFile(temp,level+1);
			}
		}
	}
}
2、字节流

–1,概述
专门用来读写 数据的,而且是各种类型 的数据. 被底层的一些工具类大量的使用.
–2,继承结构
–读取
InputStream – 父类是一个抽象类,不能new,只学习共性方法
– FileInputStream – 子类学习怎么new,方法都是继承来的
– BufferedInputStream – 子类学习怎么new,方法都是继承来的
–写出
OutputStream – 父类是一个抽象类,不能new,只学习共性方法
– FileOutputStream – 子类学习怎么new,方法都是继承来的
– BufferedOutputStream – 子类学习怎么new,方法都是继承来的
–3,学习方法
– 一般父类都会做程序设计,可能设计为抽象类或者接口,都不能new,学习父类的共性方法
– 一般子类提供的方法,都是继承自父类的,或者重写了父类的,方法不值得研究,学习子类怎么new就行

3、字节流读取

–1,InputStream父类
–是一个抽象类,不能new,只学习共性方法
–源码摘抄:public abstract class InputStream extends Object implements Closeable
–常用方法
abstract int read()
从输入流中读取数据的下一个字节。
int read(byte[] b)
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b, int off, int len)
将输入流中最多 len 个数据字节读入 byte 数组。
void close()
关闭此输入流并释放与该流关联的所有系统资源。
–2,FileInputStream子类
–子类学习怎么new,方法都是继承来的
–源码摘抄:public class FileInputStream extends InputStream
–创建对象
FileInputStream(File file)
FileInputStream(String name)
–3,BufferedInputStream子类
– 子类学习怎么new,方法都是继承来的
–BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读 取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。
–源码摘抄:public class BufferedInputStream extends FilterInputStream
–创建对象
BufferedInputStream(InputStream in)
–4,测试

	import java.io.BufferedInputStream;
		import java.io.File;
		import java.io.FileInputStream;
		import java.io.IOException;
		import java.io.InputStream;
		//测试 字节读取流
		//总结
		//1,效率上: BufferedInputStream >  FileInputStream
		//2,原因是:BufferedInputStream底层维护一个byte[],把byte[]填满了
		//程序才读取一次.减少了程序从流中的读取次数,提高了效率.
		//3,byte[] 的容量可以自己设置,也可以使用默认的,默认的是8192字节,相当于8K大小
	public class Test3_InputStream {
		public static void main(String[] args) throws IOException {
	//		method();//FileInputStream读取
			method2();//BufferedInputStream读取
		}
		//BufferedInputStream读取
		public static void method2() throws IOException {
			//1,创建多态对象
			InputStream in = new  BufferedInputStream( new FileInputStream("D:\\iotest\\1.txt"));
			//2,开始读取
			int b = 0 ;//定义变量,记录read()的返回值
			while( ( b = in.read() ) != -1) {//返回-1说明没数据了循环结束
				System.out.println(b);//打印读到的数据
			}
			//3,释放资源
			in.close();
		}
		//FileInputStream读取
		public static void method() throws IOException {
			//1,创建多态对象
			//触发String含参构造
			InputStream in = new FileInputStream("D:\\iotest\\1.txt");
			//触发File含参构造
	//		File file = new File("D:\\iotest\\1.txt") ;
	//		InputStream in2 = new FileInputStream(file);
			InputStream in2 = new FileInputStream( new File("D:\\iotest\\1.txt") );
			
			//2,开始读取 
	//		int data = in.read() ;//读取到了第一个字节
	//		System.out.println(data);
	//		System.out.println(in.read());
	//		System.out.println(in.read());
	//				
	//		//没数据了,还读,不会报错,而是永远得到-1
	//		System.out.println(in.read());
	//		System.out.println(in.read());
	//		System.out.println(in.read());
	//		System.out.println(in.read());
	//		System.out.println(in.read());
			
			//改造
			int b = 0 ;//定义变量,记录read()的返回值
			while( ( b = in.read() ) != -1) {//有数据就一直读,没数据就返回-1循环结束
				System.out.println(b);//打印读取到的数据
			}
			
			//3,释放资源
			in.close();
		//流已经关闭了,就别读了,不然会抛出异常:java.io.IOException: Stream Closed
			//System.out.println(in.read());
		}
	}
4、字节流写出

–1,OutputStream父类
–是一个抽象类,不能new,只学习共性方法
–源码摘抄:public abstract class OutputStream extends Object implements Closeable, Flushable
–常用方法
void close()
关闭此输出流并释放与此流有关的所有系统资源。
void flush()
刷新此输出流并强制写出所有缓冲的输出字节。
void write(byte[] b)
将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b)
将指定的字节写入此输出流。
–2,FileOutputStream子类
–子类学习怎么new,方法都是继承来的
–源码摘抄:public class FileOutputStreamextends OutputStream
–创建对象
FileOutputStream(File file)
FileOutputStream(File file, boolean append)
FileOutputStream(FileDescriptor fdObj)
FileOutputStream(String name)
FileOutputStream(String name, boolean append)

–3,BufferedOutputStream子类
–子类学习怎么new,方法都是继承来的
–创建对象
BufferedOutputStream(OutputStream out)
–4,测试

	import java.io.BufferedOutputStream;
	import java.io.File;
	import java.io.FileOutputStream;
	import java.io.IOException;
	import java.io.OutputStream;
	//测试 字节读写出
	//总结
	//1,效率上:BufferedOutputStream > FileOutputStream
	//2,原因是:BufferedOutputStream底层维护了一个byte[] ,把数组填满了,才写出一次,
	//减少了写出数次,提高了效率
	//3,byte[] 可以自定义容量大小,也可以使用默认的大小,默认是8192字节,相当于8K的大小
	//4,FileOutputStream 在写出数据时,默认是数据覆盖模式,也可以控制成数据追加模式

	public class Test4_OutputStream {
		public static void main(String[] args) throws IOException {
	//		method();//FileOutputStream写出
			method2();//BufferedOutputStream写出
		}
		public static void method2() throws IOException {
			//1,创建多态对象
	//OutputStream out = new BufferedOutputStream(
	//							new FileOutputStream("D:\\iotest\\1.txt") );//数据覆盖
			
	OutputStream out = new BufferedOutputStream(
							new FileOutputStream("D:\\iotest\\1.txt",true) );//数据追加
			//2,开始写出
			out.write(97);
			out.write(97);
			out.write(97);
			//3,释放资源
			out.close();
		}
		//FileOutputStream写出
		public static void method() throws IOException {
			//1,创建多态对象
	//		OutputStream out = new FileOutputStream("D:\\iotest\\1.txt");//默认发生数据覆盖
			OutputStream out = new FileOutputStream("D:\\iotest\\1.txt",true);//数据追加
	//		OutputStream out2 = new FileOutputStream(new File("D:\\iotest\\1.txt"));
			
			//2,开始写出
			out.write(97);
			out.write(97);
			out.write(97);
			out.write(97);
			
			//3,释放资源
			out.close();
		}
		
	}
5、IO练习

​ --1,文件复制
​ --思路:读取源文件的数据,并且把数据写出到目标文件中去
​ --单字节读写

			import java.io.BufferedInputStream;
			import java.io.BufferedOutputStream;
			import java.io.File;
			import java.io.FileInputStream;
			import java.io.FileOutputStream;
			import java.io.IOException;
			import java.io.InputStream;
			import java.io.OutputStream;
			import java.util.Scanner;
			// 测试 文件复制
			public class Test5_Copy {
				public static void main(String[] args) throws IOException {
					System.out.println("请您输入源文件路径:");
					String frompath = new Scanner(System.in).nextLine() ;
					File from = new File(frompath);//把路径封装成源文件
				System.out.println("请您输入目标文件路径:");
				String topath = new Scanner(System.in).nextLine() ;
				File to = new File(topath);//把路径封装成目标文件
				
				copyOf(from,to);//调用方法完成复制
				System.out.println("恭喜您,文件复制完成!");
			}
			//copyOf方法完成复制
			public static void copyOf(File from, File to) throws IOException {
				//思路,读取源文件from,写出到目标文件里to
				//1,准备读写流
				InputStream in = new BufferedInputStream(new FileInputStream(from));
				OutputStream out = new BufferedOutputStream(new FileOutputStream(to));
				//2,开始读写
				int b = 0 ;//定义变量,记录读取到的数据
				while( ( b = in.read() ) != -1 ) {//只要有数据就一直读
					out.write(b); //把读到的数据,,,,写出去
				}
				//3,释放资源
				in.close();
				out.close();
			}
		}

字符流的套路和字节流相似。

6、序列化 / 反序列化

序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

1、序列化:利用ObjectOutputStream,对象的信息,按固定格式转成一串字节值输出并持久保存到磁盘化。

2、反序列化:利用ObjectInputStream,读取磁盘中序列化数据,重新恢复对象。

注意:

1、 需要序列化的文件必须实现Serializable接口以启用其序列化功能。

2、 每个被序列化的文件都有一个唯一id,如果没有添加编译器会根据类的定义信息计算产生一个版本号。

package com.jifang.all.stream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class WriteObjet {
	public static void main(String[] args) throws FileNotFoundException, IOException {
//		//序列化		
//		ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("E:\\学习\\达内实训\\object.txt"));
//		
//		Person p = new Person("阔乐", 21);
//		os.writeObject(p);
//		os.close();
			
		//反序列化
		ObjectInputStream is = new ObjectInputStream(new FileInputStream("E:\\学习\\达内实训\\object.txt"));
		try {
			Person p = (Person) is.readObject();
			System.out.println(p.toString());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

class Person implements Serializable{
	private String name;
	private int age;
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
}

Day14—泛型+集合1

1、集合

集合

–1,概述
为了解决多个数据的存储.现有的容器是数组.
数组优势:元素都是下标,可以快速查询
数组缺点:数据类型都是统一的,遍历方式单一(下标)
为了解决数组的缺陷,又产生了集合.可以存储多个类型的数据,遍历方式很丰富.
–2,继承结构
–Collection:是集合中的顶级接口
–List – 数据有下标,查询快
–ArrayList – 底层就是数组
–LinkedList – 底层是链表,增删快
–Set – 没有下标
–HashSet
–TreeSet
–3,学习方法
–学习抽象层提供的共性方法
–学习实现类的创建对象

–4,由于集合中的元素类型可以非常丰富,如果想要限制集合中的元素类型,怎么限制呢?
–泛型技术–专门用来限制集合中的元素的类型

2、泛型

–1,概述
泛型可以约束集合中的元素类型.
泛型主要是想要模拟数组–自动检查集合中的元素类型 + 如果类型不对,直接编译期就报错
泛型 的标志是 < > ,Generics .
泛型是(Generics)是JDK1.5 的一个新特性,其实就是一个『语法糖』,本质上就是编译器为了 提供更好的可读性而提供的一种小手段,小技巧,虚拟机层面是不存在所谓『泛型』的概念的。

–2,位置
–在类上 : public interface List
–在方法上 : public abstract void toArray(T a);
–3,常用名称
–E - Element (在集合中使用,因为集合中存放的是元素)
–T - Type(Java 类)
–K - Key(键)
–V - Value(值)
–N - Number(数值类型)
–? - 表示不确定的java类型
–4,测试

import java.io.File;
			import java.util.ArrayList;
			import java.util.Collection;
			//测试 泛型 用来检查数据类型
			public class Test1_Generics {
				public static void main(String[] args) {
					//1,回顾数组 -- 数组会自动检查数据类型  +  类型不对会在编译期就报错
			//		int a[] = { 1.1 ,2 ,"3" ,4 ,5 } ;
					
					//2,泛型 -- 通常配合集合使用,标志<>
					//先不用泛型,集合中可以添加的元素类型非常丰富
					Collection c = new ArrayList() ;
					c.add(10);//向集合中添加元素
					c.add(6.6);
					c.add("rose");
					c.add( new File("") );
					System.out.println(c);
					
					//3,怎么约束集合中的元素类型??--泛型
					Collection<String> c2 = new ArrayList<>() ;
					c2.add("rose");
					//4,如果加入元素的数据类型 和 泛型约束的类型 不匹配,编译期就报错
			//		c2.add(6.6);
					
					System.out.println(c2);
					//5,泛型<X>  -- 其中X必须是引用类型,不能是基本类型
			//集合中约束了元素的类型都是引用类型Integer类型,为啥int类型的123   456 也能存呢?
					c3.add(123);//自动装箱 -- Integer.valueOf(123);
					c3.add(456);

					
				}
			}

–通用性强
–没有泛型

				//测试 泛型 的通用性
				public class Test2_Generics2 {
					public static void main(String[] args) {
						//TODO 提供方法,打印以下数组
						Integer[] a = {1,2,3,4,5};
						print(a);
               		 Double[] b = {1.1,2.2,3.3,4.4,5.5};
					print(b);
					
					String[] c = {"11","22","33"};
					print(c);
				}
				public static void print(String[] arr) {
					for (int i = 0; i < arr.length; i++) {
						System.out.println(arr[i]);
					}
				}
				public static void print(Double[] arr) {
					for (int i = 0; i < arr.length; i++) {
						System.out.println(arr[i]);
					}
				}
				public static void print(Integer[] arr) {
					for (int i = 0; i < arr.length; i++) {
						System.out.println(arr[i]);
					}
				}
				
			}

		--有泛型
			//测试 泛型 的通用性
			public class Test2_Generics2 {
				public static void main(String[] args) {
					//TODO 提供方法,打印以下数组
					Integer[] a = {1,2,3,4,5};
					print(a);
					
					Double[] b = {1.1,2.2,3.3,4.4,5.5};
					print(b);
					
					String[] c = {"11","22","33"};
					print(c);
				}
				//1,泛型的通用性,只要是泛型 约束的类型就可以了
				//2,泛型用在方法上,需要两个位置体现 : 返回值前 和参数列表中
				public static <T> void print(T[] arr) {
					//		for (int i = 0; i < arr.length; i++) {
					//			System.out.println(arr[i]);
					//		}
						//语法:for(遍历得到的数据的类型  变量名 : 想要遍历的容器){ 循环体 }
							for(T m : arr) {
								System.out.println(m);
							}
				}
			}
3、Collection接口

​ --1,概述
​ Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。

迭代map

​ --2,常用方法
​ boolean add(E e):添加元素。
​ boolean addAll(Collection c):把小集合添加到大集合中 。
​ boolean contains(Object o) : 如果此 collection 包含指定的元素,则返回 true。
​ boolean isEmpty() :如果此 collection 没有元素,则返回 true。
​ Iterator iterator():返回在此 collection 的元素上进行迭代的迭代器。
​ boolean remove(Object o) :从此 collection 中移除指定元素的单个实例。
​ int size() :返回此 collection 中的元素数。
​ Objec[] toArray():返回对象数组
​ --3,测试

import java.util.ArrayList;
		import java.util.Arrays;
		import java.util.Collection;
		import java.util.Iterator;
		//测试 Collection接口的方法
		public class Test3_Collection {
			public static void main(String[] args) {
				//1,创建对象
		//		Collection c = new Collection();//报错,因为接口不能实例化
				Collection<Integer> c = new ArrayList<>();
				
				//2,调用方法
				c.add(1); //向集合中添加元素
				c.add(2);
				c.add(3);
				c.add(4);
				System.out.println(c);
		//		c.clear();//清空集合
				System.out.println( c.contains(3) );//判断是否包含
				System.out.println( c.equals("1234") );//判断是否相等
				System.out.println( c.hashCode() );//获取哈希码值
				System.out.println( c.isEmpty() );//判断是否为空
				System.out.println( c.remove(2) );//移除元素
				System.out.println( c.size() );//获取集合的长度/元素的个数
				
				Object[] objs = c.toArray() ;//把集合里的元素,存入Object数组中
				System.out.println( Arrays.toString(objs) );
				
				//集合间的操作
				Collection<Integer> c2 = new ArrayList<>();
				c2.add(1);
				c2.add(2);
				System.out.println( c.addAll(c2) );//把c2加到c里去
				System.out.println(c);//[1, 3, 4, 1, 2]
				System.out.println( c.containsAll(c2) );//判断c里是否有c2
				
		//		System.out.println( c.removeAll(c2) );//移除掉c和c2里都有的--取差集
		//		System.out.println(c);
				System.out.println( c.retainAll(c2) );//取交集
				//仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
				System.out.println(c);
				
				//迭代集合Iterator<E> iterator() 
				//--返回一个可以迭代集合的迭代器--Iterator接口 
				Iterator<Integer> it = c.iterator() ;
				//hasNext()用来判断有没有下一个元素,有就返回true
				while( it.hasNext() ) {
					Integer i = it.next() ;//next() 获取元素
					System.out.println(i);
				}
				
			}
		}
4、List接口

​ --1,概述
​ 有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地 控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
​ 与 set 不同,列表通常允许重复的元素。列表本身允许 null 元素的话,通常它们允许多个 null 元素。
​ --2,特点
​ --List里的元素有序
​ --List里的元素都有索引
​ --List里的元素允许重复
​ --List里可以有null

img

img

List实现类

​ --3,常用方法
​ --继承自父接口Collection的方法
​ --自己的特有方法
​ void add(int index, E element)
​ 在列表的指定位置插入指定元素(可选操作)。
​ boolean addAll(int index, Collection<? extends E> c)
​ 将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
​ E get(int index)
​ 返回列表中指定位置的元素。
​ int indexOf(Object o)
​ 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
​ int lastIndexOf(Object o)
​ 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
​ ListIterator listIterator()
​ 返回此列表元素的列表迭代器(按适当顺序)。
​ ListIterator listIterator(int index)
​ 返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始
​ E remove(int index)
​ 移除列表中指定位置的元素(可选操作)。
​ E set(int index, E element)
​ 用指定元素替换列表中指定位置的元素(可选操作)。
​ List subList(int fromIndex, int toIndex)
​ 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
​ --4,测试

import java.util.ArrayList;
		import java.util.Iterator;
		import java.util.List;
		import java.util.ListIterator;

		//测试 List接口的方法
		public class Test4_List {
			public static void main(String[] args) {
				//1,创建List对象
		//		List list = new List();//List是接口,不能new
				List<Double> list = new ArrayList<>();
				list.add(1.1);
				list.add(2.2);
				list.add(3.3);
				list.add(2.2);
				list.add(2.2);
				list.add(null);
				list.add(null);
				
		//List接口的特点:有序+可重复+null+索引
				//[1.1, 2.2, 3.3, 2.2, 2.2, null, null]
				System.out.println(list);
				
				//2,调用方法
				//TODO 继承自父接口Collection的方法们
				
				//List接口的特有方法
				list.add(3, 9.9);//在指定的索引处,添加指定的数据
				System.out.println(list);
				System.out.println( list.get(0) );//按照索引获取元素
				System.out.println( list.indexOf(2.2) );//获取2.2第一次出现的索引值
				System.out.println( list.lastIndexOf(2.2) );//获取2.2最后一次出现的索引值
				System.out.println( list.remove(6) );//移除索引6对应的元素
				System.out.println( list.set(4, 0.1) );//把索引4的值替换成0.1
				System.out.println(list);
				
				List<Double> list2 = list.subList(1, 4) ;//截取子List集合,含头不含尾[1,4)
				System.out.println(list2);
				
		//迭代List集合方式1: Iterator<E> iterator()--继承自父接口Collection的,返回父接口
				Iterator<Double> it = list.iterator() ;
				while(it.hasNext()) {
					Double next = it.next();
					System.out.println(next);
				}
		//迭代List集合方式2: ListIterator<E> listIterator()--List子接口特有的返回子接口--可以向后遍历也提供了逆向遍历
				ListIterator<Double> it2 = list.listIterator() ;
				//顺序向后遍历
				while(it2.hasNext()) {//判断有没有下一个元素
					Double next = it2.next() ;//获取下一个元素
				}
				//逆向遍历--必须先顺序遍历完才能逆向! -- 了解即可
				while(it2.hasPrevious()) {//判断有没有前一个元素
					Double next = it2.previous() ;//获取前一个元素
					System.out.println(next);
				}
		//迭代List集合方式3: 因为List集合有下标,所以可以用下标遍历
				for(int i = 0 ; i < list.size() ; i++) {//list.size()集合的长度
					Double next = list.get(i);//get()根据下标i获取元素
					System.out.println(next);
				}
		//迭代List集合方式4: foreach / 增强for循环 -- 只能循环 -- 数组|Collection集合		
				//语法:for(遍历得到的数据的类型  变量名 : 想要遍历的容器){ 循环体 }
				for(Double  d : list){ 
					System.out.println(d); //打印获取到的数据
				}
				
			}
		}

ArrayList
–0,概述
List 接口的大小可变数组的实现。
每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等 于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长
–1,特点
–底层是一个数组结构
–有下标
–元素有序
–可以重复
–2,创建对象
ArrayList()
构造一个初始容量为 10 的空列表。
–3,自己的特有方法
省略-同Collection接口或者List接口
–4,测试

import java.util.ArrayList;
		//测试 ArrayList实现类
		public class Test1_ArrayList {
			public static void main(String[] args) {
				//1,创建对象
				//新语法进行了内存优化,光new不占内存,只会分配一个空数组,
				//等到你什么时候add,什么时候给数组扩容
		//源码摘抄:private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
				ArrayList<Integer> list = new ArrayList<>();
				
				//自动装箱 -- int->Integer-存入集合
				//底层实质上,是往Object[]数组里添加了数据,数组的默认容量是10
		//如果数据超出了初始容量,会自动扩容,扩容方式是1.5倍
		//源码摘抄:  int newCapacity = oldCapacity + (oldCapacity >> 1);
				list.add(9);
				list.add(8);
				list.add(7);
				list.add(6);
				list.add(5);
				list.add(4);
				//TODO 2,调用方法	
			}
		}
5、LinkedList

–1,概述
List 接口的链接列表实现。
LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了

img

​ --2,特点
​ --底层是链表结构
​ --有下标
​ --有序
​ --可以重复
​ --3,创建对象
​ LinkedList()
​ 构造一个空列表。
​ --4,常用方法
​ void addFirst(E e)
​ 将指定元素插入此列表的开头。
​ void addLast(E e)
​ 将指定元素添加到此列表的结尾。
​ E getFirst()
​ 返回此列表的第一个元素。
​ E getLast()
​ 返回此列表的最后一个元素。
​ boolean offer(E e)
​ 将指定元素添加到此列表的末尾(最后一个元素)。
​ boolean offerFirst(E e)
​ 在此列表的开头插入指定的元素。
​ boolean offerLast(E e)
​ 在此列表末尾插入指定的元素。
​ E peek()
​ 获取但不移除此列表的头(第一个元素)。
​ E peekFirst()
​ 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
​ E peekLast()
​ 获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
​ E poll()
​ 获取并移除此列表的头(第一个元素)
​ E pollFirst()
​ 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
​ E pollLast()
​ 获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
​ E pop()
​ 从此列表所表示的堆栈处弹出一个元素。
​ void push(E e)
​ 将元素推入此列表所表示的堆栈。
​ E removeFirst()
​ 移除并返回此列表的第一个元素。
​ E removeLast()
​ 移除并返回此列表的最后一个元素。

5,测试

import java.util.LinkedList;

		//测试 LinkedList
		public class Test2_LinkedList {
			public static void main(String[] args) {
				//1,创建对象
				LinkedList<Integer> list = new LinkedList<>();
				//2,调用方法
				//TODO --继承自Collection接口和List接口的方法们~~
				list.add(1);
				list.add(2);
				list.add(3);
				list.add(4);
				list.add(5);
				//LinkedList的特有方法--针对首尾元素
				list.addFirst(0);//添加首元素
				list.addLast(9);//添加尾元素
				System.out.println( list.getFirst()  );//获取首元素
				System.out.println( list.getLast() );//获取尾元素
				System.out.println( list.removeFirst()  );//移除首元素
				System.out.println( list.removeLast() );//移除尾元素
				
				list.offerFirst(100);//添加首元素
				list.offerLast(200);//添加尾元素
				System.out.println( list.peekFirst()  );//获取首元素
				System.out.println( list.peekLast() );//获取尾元素
				System.out.println( list.pollFirst()  );//移除首元素
				System.out.println( list.pollLast() );//移除尾元素
				
			}
		}
6、Set接口

​ --1,概述
​ 一个不包含重复元素的 collection。最多包含一个 null 元素。
​ --2,特点
​ --不能重复
​ --没有下标
​ --3,共性方法
​ 略,同Collection接口.

HashSet
–1,概述
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。 当你向HashSet集合中 加入数据时,先根据哈希函数将这些元素正确地分布在桶中。
对此 set 进行迭代所需的时间与 HashSet 实例的大小(元素的数量)和底层 HashMap 实例(桶的数量)的“容量”的和 成比例。
因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。

​ 底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。当然K仍然不许重复。

–2,特点
–底层是一个哈希表/散列表(桶的概念)
–元素不重复
–元素没有下标
–只能存一个null
–3,创建对象
HashSet()
构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。
–4,共性方法
同Set接口
–5,测试

import java.util.HashSet;
		//测试  HashSet实现类
		//总结
		//1,Set接口包括实现类HashSet都是  需要给数据去重时 ,才用 !
		public class Test3_Set {
			public static void main(String[] args) {
				//1,创建对象
				//特点:数据无序 + 不能重复 + 存一个null
				//本质上,创建HashSet对象,在底层,会创建一个HashMap的实例.
				HashSet<String> set = new HashSet<>();
				
				//2,调用方法
				//TODO --继承自Collection接口的方法们
				set.add("abc");
				set.add("xyz");
				//本质上,往set里存的数据,会放入map里.
				set.add("123");
				set.add("haha");
				set.add("xyz");
				set.add("xyz");
				set.add("xyz");
				set.add(null);
				
			}
		}
7、Map接口

​ --1,概述
​ 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
​ Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的 内容。HashMap映射实现则不保证顺序。

​ --2,特点
​ --HashMap<K,V>
​ --键值对 的数据结构
​ --键不能重复
​ --HashMap 是无序的
​ --TreeMap 是有序的
​ --3,继承结构
​ --Map接口
​ --HashMap ,无序的
​ --TreeMap ,有序的
​ --4,共性方法
​ void clear()
​ 从此映射中移除所有映射关系(可选操作)。
​ boolean containsKey(Object key)
​ 如果此映射包含指定键的映射关系,则返回 true。
​ boolean containsValue(Object value)
​ 如果此映射将一个或多个键映射到指定值,则返回 true。
​ Set<Map.Entry<K,V>> entrySet()
​ 返回此映射中包含的映射关系的 Set 视图。
​ boolean equals(Object o)
​ 比较指定的对象与此映射是否相等。
​ V get(Object key)
​ 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
​ int hashCode()
​ 返回此映射的哈希码值。
​ boolean isEmpty()
​ 如果此映射未包含键-值映射关系,则返回 true。
​ Set keySet()
​ 返回此映射中包含的键的 Set 视图。
​ V put(K key, V value)
​ 将指定的值与此映射中的指定键关联(可选操作)。
​ void putAll(Map<? extends K,? extends V> m)
​ 从指定映射中将所有映射关系复制到此映射中(可选操作)。
​ V remove(Object key)
​ 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
​ int size()
​ 返回此映射中的键-值映射关系数。
​ Collection values()
​ 返回此映射中包含的值的 Collection 视图。

–5,测试

import java.util.Collection;
		import java.util.HashMap;
		import java.util.Iterator;
		import java.util.Map;
		import java.util.Map.Entry;
		import java.util.Set;

		//测试 Map接口
		public class Test4_Map {
			public static void main(String[] args) {
				//1,创建对象
		//Map<Integer,String>--约束Map集合里的key的类型是Integer,value的类型是String
				Map<Integer,String> map = new HashMap<>();
				
				//2,调用方法
				map.put(9527, "唐伯虎") ;
				map.put(9530, "石榴姐") ;
				map.put(9528, "如花") ;
				map.put(9529, "秋香") ;
				//特点: 无序 + key重复的话,value会被覆盖
				map.put(9531, "如花") ;
				map.put(9528, "如花") ;
		//		map.clear(); //清空集合
				System.out.println(  map.containsKey(9000) );//判断是否包含指定的key
				System.out.println(  map.containsValue("唐伯虎") );//判断是否包含指定的value
				System.out.println(  map.equals("唐伯虎") );//判断是否相等
				System.out.println(  map.get(9530) );//根据key获取value
				System.out.println(  map.hashCode() );//获取哈希码值
				System.out.println(  map.isEmpty() );//判断是否为空
				System.out.println(  map.remove(9528) );//根据key删除记录
				System.out.println(  map.size() );//获取map的长度/元素个数
				
				Map<Integer,String> map2 = new HashMap<>();
				//2,调用方法
				map2.put(1000, "钢铁侠") ;
				map2.put(2000, "灭霸") ;
				map.putAll(map2); //把map2加到map里
				
				//迭代map集合方式1  -- 键集
		//		Set<K> keySet()  --把map里的key存到set里
				Set<Integer> set = map.keySet() ;
				//遍历set集合方式1  :  得到每个key
				Iterator<Integer> it = set.iterator() ;
				while(it.hasNext()) {//判断有没有数据
					Integer key = it.next() ;
					//拿着key回map里找value
					String value = map.get(key) ;
					
					System.out.println(key+":::::::::"+value);
				}
				
				//遍历set集合方式2  :  foreach--数组|Collection集合
				for(Integer key : set) {
					//拿着key回map里找value
					String value = map.get(key) ;
					System.out.println(key+"------"+value);
				}
				//迭代map集合方式2  --  值集
		//		 Collection<V> values()  --把map里的value们存入Collection
				Collection<String> c = map.values() ;
				System.out.println(c);//[灭霸, 唐伯虎, 钢铁侠, 秋香, 石榴姐]
				
				//迭代map集合方式3  --	键-值映射集	
		//		Set<Map.Entry<K,V>> entrySet() --把map的key和value同时封装成Entry对象存入set
				Set< Entry<Integer,String> > set2 = map.entrySet() ;
				//遍历set得到每个Entry对象
				for(Entry<Integer,String> entry : set2) {
					Integer key = entry.getKey() ;//获取key
					String value = entry.getValue() ;//获取value
					System.out.println(key+"======="+value);
				}
				
			}
			
		}
8、HashMap

​ --1,概述
​ HashMap 的实例有两个参数影响其性能:初始容量 和加载因子。容量 是哈希表中桶的数量,初始容量只是哈希 表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超 出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将 具有大约两倍的桶数。

​ 通常,默认加载因子 (0.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也 增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容 量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于 最大条目数除以加载因子,则不会发生 rehash 操作。

​ 如果很多映射关系要存储在 HashMap 实例中,则相对于按需执行自动的 rehash 操作以增大表的容量来说,使 用足够大的初始容量创建它将使得映射关系能更有效地存储。

img

–2,原理
当我们向map集合中,添加数据时.底层会根据hash算法,计算数据的存储位置.
如果这个位置没有存过数据,直接优先放在数组节点上.
如果这个位置已经存过数据了,发生了hash碰撞/hash冲突的现象.采用链表结构存储 数据,降低了查询效率.
在jdk1.8里,对于链表的数据做了优化,采用了二叉树的模式存储链表数据.提高了查询 效率.
–3,创建对象
HashMap()
构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
–4,常用方法
–同Map接口的方法

				System.out.println(key+":::::::::"+value);
			}
			
			//遍历set集合方式2  :  foreach--数组|Collection集合
			for(Integer key : set) {
				//拿着key回map里找value
				String value = map.get(key) ;
				System.out.println(key+"------"+value);
			}
			//迭代map集合方式2  --  值集
	//		 Collection<V> values()  --把map里的value们存入Collection
			Collection<String> c = map.values() ;
			System.out.println(c);//[灭霸, 唐伯虎, 钢铁侠, 秋香, 石榴姐]
			
			//迭代map集合方式3  --	键-值映射集	
	//		Set<Map.Entry<K,V>> entrySet() --把map的key和value同时封装成Entry对象存入set
			Set< Entry<Integer,String> > set2 = map.entrySet() ;
			//遍历set得到每个Entry对象
			for(Entry<Integer,String> entry : set2) {
				Integer key = entry.getKey() ;//获取key
				String value = entry.getValue() ;//获取value
				System.out.println(key+"======="+value);
			}
			
		}
		
	}

#### 8、HashMap

​	--1,概述
​		HashMap 的实例有两个参数影响其性能:初始容量 和加载因子。容量 是哈希表中桶的数量,初始容量只是哈希		表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超			出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将			具有大约两倍的桶数。 

​	通常,默认加载因子 (0.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也			增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容		量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于			最大条目数除以加载因子,则不会发生 rehash 操作。 

​	如果很多映射关系要存储在 HashMap 实例中,则相对于按需执行自动的 rehash 操作以增大表的容量来说,使		用足够大的初始容量创建它将使得映射关系能更有效地存储。

[外链图片转存中...(img-VsbdHYiw-1597894588554)]

--2,原理
	当我们向map集合中,添加数据时.底层会根据hash算法,计算数据的存储位置.
	如果这个位置没有存过数据,直接优先放在数组节点上.
	如果这个位置已经存过数据了,发生了hash碰撞/hash冲突的现象.采用链表结构存储		数据,降低了查询效率.
	在jdk1.8里,对于链表的数据做了优化,采用了二叉树的模式存储链表数据.提高了查询		效率.
--3,创建对象
	HashMap() 
      	构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
--4,常用方法
	--同Map接口的方法

  --5,测试
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值