2020-10-31

关于最近学习的分享

咳咳,无敌靓仔又来了哈哈,我来给你们分享一下我最近学习的状况。嗯。。。怎么说呢,有点迷,最近学习了集合还有线程。方法很好,很实用,但是记得太多了,有很多很多方法,前面一段时间学习感觉还可以,但是最近感觉学习的不怎么样,很迷。
但是,每个人都有自己的学习方式,我下来做总结复习,然后我觉得还可以,就是不管怎么说,学习什么东西都得靠自己,拼不了父母就拼自己的命,我相信终有一天,我会出人头地。不畏过去,不畏将来.奥力给!!!
下面由靓仔同学为大家分享学习的成果

1.接口和抽象类的区别

​	三个:
	抽象类:
		成员变量:可以是变量也可以是常量
		成员方法:可以 是抽象方法也可以是非抽象方法
		
		构造方法:存在,继承关系(无参构造/有参构造),对数据进行初始化
	接口:
		只能是常量:
		存在默认修饰符:public static final
		成员方法:只能是抽象方法,默认修饰符:public abstract
		构造方法:不存在构造方法
		
	2)关系的区别
		类与类之间:单继承,并不能多继承,可以多层继承
		类与接口:实现关系,继承一个类的同时,也可以实现多个接口
		接口与接口:继承关系,也可以但继承,可以多继承
	3)设计理念的区别
		抽象类---->继承关系----体现的一种"is a"关系
		接口----->提供额外的功能----体现的一种"like a"的关系
		
		
2.Object类中的toString方法的含义是什么
object代表任意的Java类型,直接输出对象名称相当于调式这个对象的toString()方法,默认的打印出来是一个包名.类名@十6进制数据(地址值)
Object类的任意子类都需要重写toString(),能够描述当前对象的简易并且易于读懂的信息表达式
	atl+shift+s--s
	
3.equals和==的区别
==:如果连接的两个基本数据类型(整数默认:int) 比较的是两个数据值是否相等
		   如果连接的是两个引用数据类型:比较的是两个对象的地址值是否相等
		   
		equals方法:属于Object类的一个方法
					如果不重写Object类中eqauls方法,默认比较的是地址值是否相等;重写Object
					类中的equals方法,比较的是两个对象的内容(成员变量..)是否相等
								public boolean equals(Object obj){
										return (this==obj);
								}
4.final关键字的特点
final关键字:
			状态修饰符:最终的,无法更改的
			可以修饰类,该类不能继承
			修饰成员变量,此时变量是一个常量   : public static  final 基本数据类型:int num = 100 ;(编译时期常量:不需要通过Jvm加载)
												public static  final Integer num = 100 ; 运行时期常量(需要加载这个类型)
			可以修饰成员方法:此时方法不能重写!
			
			finally
			finalize()
5.多态的前提条件以及成员访问特点
1)继承关系
			2)存在方法重写
			3)父类引用指向子类对象(向上转型)
			
			成员访问特点:
					Fu f = new Zi() ;
					成员变量:编译看左边,运行看左边
					成员方法:编译看左边,运行看右边:存在方法重写
					静态的方法:编译看左,运行看左
					构造方法:继承关系--->分层对数据进行初始化
6.匿名内部类的格式以及本质是什么?
new 类名(抽象类)/接口名(){
			重写方法(){...}
	};
	本质:继承了该抽象类或者实现了接口的子类对象!
	
	
	
	
	
	www.jd.com 门户网站---- 服务器 ip地址   张三,登录了
	shouji.jd.com  ----- 服务器
	item.jd.com
	cart.jd.com
protected Object clone() throws CloneNotSupportedException
 		克隆方法:创建并返回此对象的一个副本
  //Object 类的 clone 方法执行特定的复制操作。
		首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。
 import java.io.InputStream;/字节输入流
 import java.io.PrintStrem;//字节打印流
 
Scanner类中提供了一些判断功能:

	public boolean hasNextXXX():判断当前是否是执行XXX类型
 				(xxx)int,short,float,double...
 				public XXX nextXXX() :接收指定XXX类型
 举例:
 public boolean	haxNextInt() :判断接收的类型是否是int类型
  				
  				public int nextInt()  : 接收指定的int类型的数据
Scanenr:键盘录入的细节问题
  		先录入int类型,在录入String类型 (nextLine())
  
  问题:
 		当前字符串录入数据:值就被漏掉了,原因就是回车符号(本身字符串)
  
  在下一次录入String类型前,再次创建一个Scanner类型对象
 所以; 先录入int数据,在录入String类型数据
7.String类型的判断功能
		public boolean equals(Object anObject):比较两个字符串内容是否相同
  		public boolean equalsIgnoreCase(String anotherString):不区分大小写比较
  		public boolean startsWith(String prefix):判断是否以指定的子串开头
 		public boolean endsWith(String suffix):判断是否以指定的子串结尾
  		public boolean isEmpty():判断字符串是否为空
  		
  		开发中:
 		equals()
		equalsIgnoreCase()
		startsWith()..
8.String类的获取功能:
int length():获取字符串长度
  	public char charAt(int index):获取指定索引处的字符
 	public String concat(String str):字符串拼接功能:使用当前字符串和指定str字符串进行拼接
  	public int indexOf(int ch):获取指定字符在此字符串中第一次出现索引值
  	public int indexOf(String str):获取指定字符串在此字符串中第一次出现索引值
9.String类 的分割功能
public String[] split(String regex):通过指定的字符串进行分割,返回值字符串数组
10.String类转换功能:
public char[] toCharArray():将字符串转换成字符数组
public byte[] getBytes() :将字符串----变成字节数组 (过程:编码)
public static String valueOf(XXX xx):可以将任何类型的数据转换成String


举例:
  						int i = 100 ;---->int  --- String
  					String.valueOf(i) ;---->"100"
  					
  					
  					
  		public String toUpperCase():将此字符串转换成大写
  		public String toLowerCase():将此字符串转换成小写

public class StringDemo2 {
	
	public static void main(String[] args) {
		
		String s = "helloJavaEE" ;
		//public char[] toCharArray():将字符串转换成字符数组
		char[] chs = s.toCharArray() ;
		for(int x = 0 ; x < chs.length ;x ++) {
			System.out.print(chs[x]+" ");
		}
		System.out.println();
		System.out.println("--------------------------------");
		//	public byte[] getBytes() :将字符串----变成字节数组 (过程:编码)
		byte[] bytes = s.getBytes() ;
		for (int i = 0; i < bytes.length; i++) {
			System.out.print(bytes[i]+" "); //字符的内容在ASCII码表中寻找对应的整数值
		}
		System.out.println();
		System.out.println("---------------------------------");
		//public static String valueOf(XXX xx):可以将任何类型的数据转换成String
		int i = 100 ;
		String s2 = String.valueOf(i) ;
		System.out.println("s2:"+s2);//"100"
		System.out.println("---------------------------------");
		//public String toUpperCase():将此字符串转换成大写
		System.out.println("toUppcase():"+s.toUpperCase());
		//public String toLowerCase():将此字符串转换成小写
		System.out.println("toLowerCase():"+s.toLowerCase());
		
	}
}

1.String类的特点,以及String类作为参数有什么特点

String是一个常量,一旦被赋值,其值不能被改变!
作为形参的特点:形参的改变不会影响实际参数!效果和基本类型作为形参

2.写出String 类的常用方法列出10个

	获取功能:
		int length():获取字符串长度
		public String concat(String str):拼接功能
		public String[] split(String str):通过特点字符串内容将字符串拆分成字符串数组
		char charAt(int index):获取指定索引处的字符
	转换的:
		public char[] toCharArray():将字符串转换成字符数组
		public byte[] getBytes():平台默认编码集:将字符串转换成字节数组
		public static String valueOf(int/double/float..../Object):
							可以将任何类型的数据转换成String类型
		public String toUppCase():将字符串内容转换成大写.....toLowerCase():转换成小写
	判断功能;
		public boolean isEmpty():判断字符串是否为空
				public boolean equals(String anotherString):比较字符串的内容是否相同
				....

4.static关键字的特点

		1)随着类的加载而加载
		2)优先于对象存在,不存在this关键字
		3)可以被多个对象共用
		4)可以被类名直接访问
				类名.变量名;
				类名.方法名();
5.成员变量和局部变量的区别
		书写位置
				成员变量:类中,方法外
				局部变量:方法定义中或者方法声明上
		内存位置:
				成员变量:堆内存中
				局部变量:栈内存中
		生命周期:
				成员变量:随着对象的创建而存在,随着的对象创建完毕而消失(不会立即被回收,等待GC空闲时回收)
				局部变量:随着方法调用而存在,随着方法调用完毕而消失
		初始化
				成员变量:存在系统默认初始化
				局部变量:在使用之前必须赋值,否则"可能尚未初始化"

6.String类的截取功能

public String substring(int beginIndex):从指定位置开始截取,默认截取末尾
public String substring(int beginIndex,int endIndex):从指定位置开始截取,到指定位置结束,但是包含beginIndex,不包含endIndex索引(包前不包后)

7.替换功能

public String replace(char oldChar,char newChar):将以前的字符用心的字符替换掉
public String replace(String oldStr,char newStr):将以前的字符用心的字符替换掉
public String trim():去除两端空格
 public int compareTo(String anotherString);两个字符串按照字典顺序比较的结果(相同就进行下一位直到不相等,如果的一个不相等直接相减)
eg
给定一个int类型数组,将它拼接为字符串格式
 
  int[] arr = {11,22,33,44,55} ;
  
  "[11, 22 ,33, 44, 55]"
  
  方式1:
  		使用"" + 任何数据= 字符串数据
  方式2:
  		使用String类的concat()拼接功能

8.反转功能

StringBuffer里面reverse(),可以直接将缓冲区中字符串内容反转!
字符串反转一步走
		return new StringBuffer(s).reverse().toString();

9.类型转换

1)String <----> StringBuffer类型的相互转换
StringBuffer sb = new StringBuffer(s) ;
2)其它类型转换
String----->int	:Inerget.parseInt(String str)
String----->long :Long.parseLong(String str)
String----->double:Double.parseDouble(String str)
int------>String: Integer.toString(int i)

10.StringBuffer删除功能

public StringBuffer deleteCharAt(int index):删除指定位置处的字符,返回缓冲区本身
public StringBuffer delete(int start,int end):删除从指定位置到指定位置结束(包前不包后,end-1位置)

11.面试题

1)StringBuffer和数组的区别?
不同点:
	他们两者都属于引用类型,而且都是"容器"
	StringBuffer: 可变的字符序列 (长度可变的)
	里面可以存储任何数据类型----->都是以"字符"进行拼接 通过append追加length()
	
	数组: 长度固定,只能存储同一种类型的元素
相同点:
	两者之间互相兼容的,功能是相同(添加,构造方法,替换,删除,截取..)
2)StringBuffer与StringBuilder的区别
StringBuffer:可变的字符序列
	线程角度:线程安全的--->同步的---->执行效率低
	在单线程程序中,StringBuilder去替换StringBuffer,因为效率高!
StringBuilder:可变的字符序列
	线程角度:线程不安全的---->不同步的---->执行效率高
13.每一个基本类型提供了对应的引用类型
		byte			Byte
 		short			Short
  		int				Integer
  		long			Long
  		
  		float			Float
  		double			Double
  		char			Character
  		boolean			Boolean
  		
  Integer类:包含了int类型的值
 
  public static String toBinaryString(int i):将整数值以"二进制"文本形式体现..
  public static String toOctalString(int i)
  public static String toHexString(int i)
  
  成员变量(字段)
  		public static final int MIN_VALUE:最小值
  		public static final int MAX_VALUE:最大值
  		
  		Integer类的构造方法
  		Integer(int value) :将int类型包装了Integer类型
Integer(String s)  :将字符串内容包装Integer类型
		注意事项:
					String是一个数字字符串,否则出现异常!

14.Jdk5提供一些特性

Jdk5提供一些特性:自动拆装箱功能,后面:   静态导入(导入到方法的级别:前提方式静态的),可变参数(public static 返回值类型 方法名(int ...))
  				,增强for循环(集合),泛型:类名/接口名<引用类型>
   举例:
   		基本类型----引用类型: 自动装箱	int---->Integer
   		引用类型---基本数据类型 : 自动拆箱	:Integer --int

15.构造方法

Character:char类型的包装类类型,包含一个char类型的值
  构造方法
  public Character(char value)
  
  判断功能:
  		public static boolean isDigit(char ch):判断当前字符是否是数字字符
 		public static boolean isLowerCase(char ch):判断当前字符是否是小写字母字符
 		public static boolean isUpperCase(char ch):判断当前字符是否是大写字母字符

StringBuffer,StringBuilder和数组的区别

前两个都是字符串缓冲区,都支持可变的字符序列,有相同的api
	前者:它是一个线程安的,-----同步的----->执行效率低(线程安全的类)
	后者:它是一个线程不安全的---不同步的---->执行效率高
		单线程程序---->考虑效率问题---->后者会将前者替换掉!
		多线程程序--->最重要的安全问题---->StringBuffer了
	
他们和数组:
		都容器,都可以存储数据的!
		字符串缓冲区:存储数据最终以"字符序列"存储的(StringBuffer/StringBuilder)
					长度可变,可以不断追加:append(xxx)
					字符串遍历:length()+charAt(int index)
		数组:只能存储同一种类的元素
					长度是固定的,(也是数组的弊端)
					数组的遍历:length属性:获取数组长度

StringBuffer列举出几个常用的方法

public StringBuffer  append(int/String/char/double/float.../Object)
		public String substring(int beginIndex)
		public String substring(int beginIndex,int endIndex)
		构造:
			StringBuffer()
			StringBuffer(String str)
		public StringBuffer deleteCharAt(int index)...

String类列举出5个常用方法

String char[] toCharArray()
		public char chaAt(int index)
		public boolean equals(String otherStr)
			public String substring(int beginIndex)
			public String substring(int beginIndex,int endIndex)
		public int indexOf(char ch/String):查询当前字符或者子串第一次出现的索引值!

Integer i = 128 ;

Integer i2 = 128 ;

i==i2 结果是什么.为什么
   false, 将常量直接赋值给Integer类型的变量:执行Integer.valueOf(i)
		判断i的值是否在IntegerCache(内部类中)的缓存区 low= -128  high = 127范围之内,
		在范围内,直接从缓存区中取数据;如果超出了范围,它会执行new Integer(i),地址值不一样,就是false

选择排序和冒泡排序的思想区别,核心代码体现

使用0角标对应的元素依次和后面角标对应的进行比较,小的往前放,第一次比较完毕,最小值
出现在最小索引处,依次这样比较.1,2,3....角标对应的元素比较....

    冒泡排序:
			两两比较,将教大的值往后放,第一次比较完毕,最大值出现在最大索引处,依次比较,就可以得到排序的数组
			规律:
				第一次:有0个不比
				第二次:有1个不比
				
				比较的次数:数组长度-1次
​```java
Object类:
   toString()
   equals()
   getClass()----对象名.getClass()----class 包名.类名
   
String类:
   构造方法:   无参/有参
    String()/String(byte[] bytes):解码 
    String(StringBuffer buffer)
    转换功能:
        public byte[] getBytes() :编码
        public char[] toCharArray()
        public String valueOf(任何类型数据)
    截取功能:
    	public String substring(int beginIndex)
		public String substring(int beginIndex,int endIndex)
    获取功能
    	public int indexOf(char ch/String):查询当前字符或者子串第一次出现的索引值!
        public String[] split(String str):分割/拆分
        public String concat(String str):拼接
        public int length() 
    判断功能:
	    public boolean equals(String otherStr)
            
 StringBuffer:
		反转功能:
        public StringBuffer reverse() 
        截取
        替换...
        添加/删除
        构造方法:
        StringBuffer()  /StringBuffer(String str)
            
            
            
Integer :
     Integer(int value)
     Integer(String str):数字字符串,否则出异常
     
 jdk5自动拆装箱:
基本类型---引用类型:装箱
引用类型---基本类型:拆箱

int---String类型的相互转换
String---->int : Integer类的静态功能:public static int parserInt(String s)(重点)
int----->String:Integer类的静态功能
          public static String toString(int i)

1)java.lang.Math:

```java
Math类包含用于执行基本数学运算的方法,如初等指数,对数,平方根和三角函数.
public static double abs(double a...);求某个数据的绝对值
public static double ceil(double a...);向上取整
public static double floor(double a...);向下取整
public static int min(int a,int b);求两个int数据的最小值
public static int max(int a,int b);求两个int数据的最大值
public sattic double random();随机数---------> Java提供随机数生成器:Random类 nextInt(int n)
public static int round(float a):四舍五入...
public static long round(double a);
public static double sqrt(double a):开根(一个正整数的平方根)  4---2
public static double pow(double a,double b):返回结果:a的b次幂

2)静态导入----jdk5新特性:导入到方法的级别!

动态导入:
 	import 包名.类名;
  	import java.util.Date/Scanner/List/ArrayList....
   
  静态导入的格式:
  		import static 包名.类名.方法名;
 
  前提这些方法是静态 的
  
使用静态导入的注意事项:
 		如果当前类中出现了和导入的静态方法名一样,冲突了,在使用静态导入的这个的方法的时候
  就必须带上限定(包名.类名)

3)java.util.Calendar类:日历类

	Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 		等 日历字段之间的转换提供了一些方法,
	Calendar不能直接实例化!
	首先里面会存在一些静态功能,静态功能的返回值就是该类本身
	public static Calendar getInstance()
	public int get(int field):获取的日历字段的值!
	参数:传递日历字段
Calendard的成员方法:
	给日历字段添加或减去时间偏移量:public abstract void add(int field,int amount)
	日历对象.add(Calender.DATE,-5);当前日历时间的五天前
	设置当前年月日,日历时间
	
	public final void set(int year,int month,int date)
		public class CalendarDemo2 {
	
	public static void main(String[] args) {
		
		//创建日历类对象
		Calendar c = Calendar.getInstance() ;
		
		int year = c.get(Calendar.YEAR) ;
		int month = c.get(Calendar.MONTH) ;
		int date = c.get(Calendar.DATE) ;
		System.out.println(year+"-"+(month+1)+"-"+date);//2020-10-21当前日期时间
		
		System.out.println("--------------------------");
		//3年前的今天
		//public abstract void add(int field,int amount)
		/*
		c.add(Calendar.YEAR, -3);
		int year2 = c.get(Calendar.YEAR) ;
		System.out.println(year2+"-"+(month+1)+"-"+date);
		*/
		
		//5年后的10天前
		//对年设置偏移量,DATE设置偏移量
		c.add(Calendar.YEAR, 5);
		c.add(Calendar.DATE, -10);
		int year2 = c.get(Calendar.YEAR) ;
		int date2 = c.get(Calendar.DATE) ;
		System.out.println(year2+"-"+(month+1)+"-"+date2);
		
		System.out.println("----------------------------------");
		//public final void set(int year,int month, int date)
		c.set(2018, 4,12);
		int year3 = c.get(Calendar.YEAR) ;
		int month3 = c.get(Calendar.MONTH) ;
		int date3 = c.get(Calendar.DATE) ;
		System.out.println(year3+"-"+(month3+1)+"-"+date3);
	}
}

/*
 * 键盘录入年份,求出年份的2月份有多少天!
 * 
 * 分析:
 * 	1)创建键盘录入对象,录入年份  int 
 * 	2)创建日历类对象 getInstance(): Calendar
 * 	3)通过set(int year,int month,int date) :设置一个时间
 * 		 year:键盘录入的	  2       1
 * 
 * 	Calendar对象.set(year,2,1) ;---->实际应该当前年份的3月1日 (month:从0-11)
 * 给月中某一天设置偏移量
 * 		add(Calendar.DATE,-1)
 * 
 * 输出:Calendar对象.get(Calendar.DATE);
 * */
 public class Test {
	
	public static void main(String[] args) {
		
		//创建键盘录入对象
		Scanner sc = new Scanner(System.in) ;
		
		//提示并录入数据
		System.out.println("请您输入年份值:");
		int year = sc.nextInt() ;
		
		//创建日历类对象
		Calendar c = Calendar.getInstance() ;
		//设置日历时间
		c.set(year, 2,1); //实际应该3月1日  month+1
		//再次设置对DATE字段(月中某一天)设置偏移量
		c.add(Calendar.DATE, -1); //算出:2月份的最后一天(得到具体的天数)
		
		System.out.println("当前年份有:"+c.get(Calendar.DATE)+"天");
	}
}

java.util.Date类

 特定的瞬间,精确到毫秒

改造方法:
	public long getTime():返回197011日所表示的时间毫秒
	public class DateDemo {

	public static void main(String[] args) {
		//创建Date对象
		Date date = new Date() ;
		System.out.println(date);//date格式: //Wed Oct 21 11:44:48 CST 2020
		
		System.out.println("--------------------");
		long time = date.getTime() ;
		System.out.println(time);//1603252011219
		

关于String文本格式和Date日期格式相互转换

*
 *
 关于
 * String文本格式  和Date日期格式相互转换
 * 	
 * Date---------------->String 日期文本格式  "格式化"操作
 *
 * 	java.text.DateFormat:可以将日期和文本相互转换
 * 
 * DateFormat继承自Format类:都是抽象类,不能直接实例化!,提供更具体的子类
 * 		java.text.SimpleDateFormat extends DateFormat
 * 它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)
 * SimpleDateFormat的构造方法
 * 
 * 	public SimpleDateFormat(String pattern):
 *   创建一个SimpleDateFormat对象
 *   	参数:指定一个模式 要遵循一定的规则(jdk对它规定了)
 *   
 *   	y:------2020		"yyyy"
 *   	M:年中月份----10/03   "MM"
 * 		d;月中的天数----05/21  'dd'
 * 		h:表示上午/下午的小时数  hh
 * 		H:一天中的小时数		  HH
 * 		m:分钟数				  mm
 * 		s:秒数				  ss
 * 模式
 * "yyyy-MM-dd HH:mm:ss" 
 * 	"yyyy年MM月dd日 HH时mm分ss秒" 
 * Date---->String
 * 格式化的步骤:
 * 	1)存在Date对象
 *  2)创建SimpleDateFormat(String pattern)
 *  3)public final String format(Date date):格式化方法
 *  
 *  解析
 *  String----->Date 
 *  步骤:
 *  	1)存在String  "日期文本"   "2020-10-21"
 * 		2)创建SimpleDateFormat(String pattern)
 * 		3)public Date parse(String source)  throws ParseException
 * 解析:
 * 		SimpleDateFormat中的参数模式:必须和String 日期文本格式一致,否则出现解析异常(ParseException)
 * */
 public class DateDemo2 {
	
	public static void main(String[] args) throws ParseException {
		//创建一个日期对象
		Date date = new Date() ;
		System.out.println(date);//Wed Oct 21 14:10:48 CST 2020 Date格式
		
		//2)创建SimpleDateFormat:格式化的桥梁
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd") ;//年-月-日
		//3)格式化操作
		String dateStr = sdf.format(date) ;
		System.out.println(dateStr);
		
		System.out.println("------------------------");
		
		//日期文本
		String source = "2022-6-30 20:00:30" ;
		//String---->Date
		//创建SimpleDateFormat对象
		//必须和String 日期文本格式一致
		//SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日") ;
		SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
		//解析:抛出一个异常
		Date d = sdf2.parse(source) ;
		System.out.println(d);//Thu Jun 30 20:00:30 CST 2022
	}
}
public class DateUtils {

	private DateUtils() {
		
	}
	
	/**
	 * 这个方法是将Date日期格式转换成日期文本格式
	 * @param date  当前日期对象
	 * @param pattern 指定模式 yyyy-MM-dd(年月日)
	 * @return 返回的结果表示是当前日期文本
	 */
	public static String date2String(Date date,String pattern) {
		//分步走
		//创建SipleDateFormat对象
		/*
		SimpleDateFormat sdf = new SimpleDateFormat(pattern) ;
		//格式化
		String dateStr = sdf.format(date) ;
		return dateStr ;
		*/
		return new SimpleDateFormat(pattern).format(date) ;
	}
	
	/**
	 * 这个方法是将日期文本转换成日期格式
	 * @param source  已知存在的日期文本
	 * @param pattern  指定模式 yyyy-MM-dd(年月日)
	 * @return 返回的结果是日期格式Date
	 * @throws ParseException 
	 */
	public static Date string2Date(String source,String pattern) 
			throws ParseException {
		//创建SimpleDateFormat对象
		/*
		SimpleDateFormat sdf = new SimpleDateFormat(pattern) ;
		Date date = sdf.parse(source) ;
		return date ;
		*/
		return new SimpleDateFormat(pattern).parse(source) ;
	}
}

System类

```java
包含一些有用的类字段和方法,它不能被实例化
public static final InputStream in:标准的"输入流"
public static final PrintStream out:标准的"输出流"
键盘录入:	
 * 			Scanner(InputStream in) ---->Scanner(System.in)
 * 
 * 输出语句:
 * 		System.out.println("xxx")----->System.out--->PrintStream ps (字节打印流)
 * 						ps.println("x") : 字节打印流调用方法名println(String str)

import java.util.Arrays;

`

public static void arraycopy(object src,int srcPos,Object dest,int destPos,int length)
从原数组中的指定位置开始进行复制指定length长度复制到目标数组中的某个位置
 * 		参数1:指定源数组
 * 		参数2:源数组中的某个位置
 * 		参数3:目标数组对象
 * 		参数4:目标数组对象中的某个位置
 * 		参数5:指定几个元素复制(长度)
 int[] arr1 = {11,22,33,44,55} ;
		int[] arr2 = {1,2,3,4,5,6} ;
		//复制之前
		System.out.println(Arrays.toString(arr1));
		System.out.println(Arrays.toString(arr2));
		
		System.arraycopy(arr1, 2, arr2, 3, 2);
		System.out.println("-----------------------");
		System.out.println(Arrays.toString(arr1));
		System.out.println(Arrays.toSt

import java.io.IoException;

public static void exit(int static);参数为零,表示正常终止jvm
public static long currentTimeMillis():获取当前系统时间的毫秒值

        public class SystemDemo {

            public static void main(String[] args) throws IOException {

                System.out.println("程序开始了...");

                //System.exit(0); //jvm终止了

                System.out.println("程序结束了...");
                System.out.println("---------------------------------");

                //public static long currentTimeMillis():将当前系统时间---换算成毫秒值
                //一般不单独使用
                //long time = System.currentTimeMillis() ;
                //System.out.println(time);//1603265022062

                //计算某个程序的执行速度:耗时多长时间
                long start = System.currentTimeMillis() ;

                //for循环
                for(int x = 0 ; x < 10000; x ++) {
                    System.out.println("hello"+x);
                }
                long end = System.currentTimeMillis() ;
                System.out.println("for循环共耗时:"+(end-start)+"毫秒") ;//234毫秒

                //java提供类:Runtime类:代表每一个Java程序的运行实例(Java设计:单例模式) 和系统运行环境相连接!
                Runtime r = Runtime.getRuntime() ;
                //获取计算机当前cpu的核数
                System.out.println(r.availableProcessors());//8

                //exec(String command):参数:输出 指令
                r.exec("mspaint") ;
            }
        }

java.util.Random:随机数生成器

构造方法
public Random():(推荐),产生的随机数是变化的
public Random(long seed):每次产生的随机数是固定的!
成员方法:
public int nextInt():获取的是in挺范围内的随机数
public int nextInt(int n):获取0到n之间的随机数[0,n)
获取随机数两种方式:
Math类的random()方法:返回值double类型Random类空参构造=(int n):获取随机数

public class RandomDemo {
	
	public static void main(String[] args) {
		
		//创建一个随机生成器对象
		Random r = new Random() ;
		//	public Random(long seed)
		//Random r = new Random(1111) ;
		
		//获取10个随机数
		for(int x = 0 ; x < 10 ; x ++) {
			//调用它的成员方法
			//public int nextInt():取的int类型范围内
			//int num = r.nextInt() ;
			
			//public int nextInt(int n) :0-n之间的随机数
			int num = r.nextInt(100)+1;
			
			System.out.println(num);
		}
	}
}

什么是对象数组?

能够储存对象的数组


使用数组存储引用数据类型是可以实现的,但是它不满足长度可变的需求,Java提供了 ---"集合",支持长度可变的
集合特点:只能存储引用数据类型!

集合和数组的区别?

集合和数组都是"容器",储存元素!
		1)长度的区别
			数组的长度:固定的
			集合的长度:可变的
		2)储存数据类型的区别
			数组:可以储存基本数据类型,也可以储存引用数据类型
			int[]   String[]  Student[]
			集合:只能储存引用数据类型
		3)储存元素的区别
			数字:只能储存同一种数据的元素
				举例:水杯中"纯净水"
			集合:可以储存任意类型的元素(类型:引用类型)
			
		Collection:某些集合可以储存从重复元素,某些集合不能重复元素
		一些集合有序,一些集合无序(有序/无序:储存元素和取出元素是否一直)
		JDK 不提供此接口的任何直接 实现:
  				它提供更具体的子接口(如 Set 和 List)实现
  				java.util 
  					Collection接口(单例集合的根接口)

基本功能

添加功能:boolean add(Object e):将任何数据类型添加道集合中
​	删除功能:void clear ();暴力删除

​		boolean remove(object o):移出指定的元素

​	判断功能:boolean contains(Object o):判断是否包含指定的元su	

​		boolean isEmpty();判断集合是否为空,如果为空,则返回true

​	Collection高级功能

​		boolean addAll(Collection c):添加所有

​		boolean containsAll(Collection c);包含所有(包含一个算包含还是包含所有?)boolean removeAll(Collection c):删除所有 (删除一个还是删除所有算是删除?)boolean retainAll(Collection c):一个集合对另一个集合取交集 

​	转换功能:

​		Object[] toArray():将集合转换成对象数组

​		Iterator iterator():Collection集合的迭代器(集合的遍历方式)
public class CollectionDemo {
	public static void main(String[] args) {
		
		//创建一个Collection集合对象
	//	Collection c = new Collection() ;//接口不能实例化,提供了更具体的子实现类
		
		Collection c = new ArrayList() ; //接口多态!
		System.out.println(c);//[] 
		System.out.println("------------------------------");
		//System.out.println(c.add("hello")) ;
		//System.out.println(c.add("world")) ;
		//System.out.println(c.add("javaee")) ;
		/*
		 * 集合的add源码:只要添加元素,最终的结果是true
		 * */
		c.add("hello") ;
		c.add("world") ;
		c.add("javaee") ;
		System.out.println(c);
		System.out.println("------------------------------");
		
		//boolean remove(Object o):移出指定的元素
		System.out.println("remove:"+c.remove("hello"));
		void clear()
		//c.clear();
		//boolean contains(Object o)
		System.out.println("contains:"+c.contains("ak"));
		System.out.println("contains:"+c.contains("javaee"));
		//boolean isEmpty()
		System.out.println(c.isEmpty());
		
		System.out.println(c);
		
		
	}
}

Collection集合的高级功能:

Collection集合的高级功能:
  		boolean  addAll(Collection c):添加一个集合中的所有元素
		boolean  removeAll(Collection c):问题:是删除一个算删除还是删除所有算删除?
		boolean  containsAll(Collection c):问题:包含一个算包含还是包含所有算包含?
		public boolean retainAll(Collection c) 取交集
		boolean的真实含义是什么:
 		@author zhangyang
 Collection集合的高级功能:
  		Object[] toArray()
  		Iterator iterator():Collection集合的专有遍历方式
  iterator()的返回值是接口:需要返回的是该接口的子实现类对象!
 	
  	Iterator:存在一个方法
  			Object next():获取下一个元素
  		
  			boolean hasNext():判断当前迭代器中是否有下一个可以遍历元素,
  如果存在,则返回true;	
  

		
		

迭代器的注意事项

		1)Object next()获取当前集合的元素(),不能使用多次,使用一次即可,
  			获取所有元素信息
  		2)能使用for循环,不推荐(因为以后集合中元素可能不知道个数,使用while循环)
  		
  		//获取迭代器
		Iterator it = c.iterator() ;

泛型

什么是泛型
	格式
		<数据类型:引用数据类型>
	特点:
		将集合的类型在创建的时候就明确,保证集合操作的安全性1
	好处:
		1)避免了强制类型转换
		2)将运行时期异常提前到了编译时期
		3)解决了黄色警告线的问题
		4)提高了程序的安全性
泛型可以运用在那些地方
	泛型在集合中使用居多,也可以定义类上,也可以放在方法上,也可以放在接口上!
	
	没有加入泛型之前,程序存在安全隐患,出现类型不区配
	eg:ClassCastException:属于运行时期异常!
	
	//将泛型定义在类上
	//定义一个工具类
	public class ObjectTool<T> {
	
		//成员变量:定义Object类型
		private T obj ;
	
		//设置一个set方法:赋值
		public void set(T obj) {//"高圆圆": Object obj = new String("高圆圆")
		this.obj = obj ;
		}
	
		//get方法:获取信息
		public T get() {
		return obj ;
		}
	}
	1)将泛型定义在方法上,方法形式和泛型类型保持一致
	2)将泛型定义在方法上
		public<T> void show(T t){
			//输出
		}
	3)将泛型可以定义在接口上
        public interface Inter<T>{
        void inter( T t);
   		 }
		1)将泛型定义在接口上,子类实现明确了类型是什么类型
            	public class InterImpl implements Inter<String>{
                    @Override
                    public void inter(String t){
                        System.out.println("hello"+t);
                    }
                }
		2)将泛型定义在接口上:接口的子实现类不明确类型
            	public class InterImpl<T>implements Inter<T>{
                    @Override
                    public void inter(T t){
                        System.out.println("heloo"+t);
                    }
                }
泛型的高级通配符:<?>
    当前Object类型/任意Java类型(自定义?jdk提供...)
    <? extends E>:向下限定:E类型以及它的子类
    <? extends E>:向上限定:E类型以及它的子类(最起码和前面的类型保持一致)

List集合

extends Collection
	有序的集合,可以容许元素重复!
有序性:储存和取出一致
		使用List集合存储字符串并遍历
 		使用List集合存储自定义对象并遍历(自己完成!)
 	两种方式:
 		1)Object[] toArray()
 		2)Collection集合的Iterator
			//迭代器
			Iterator<String> it = list.iterator() ;
			while(it.hasNext()) {//判断是否有下一个数hasNext()
			String s = it.next() ;
			System.out.println(s+"---"+s.length());
			}
List集合的特有功能:
	添加功能:
		void add(int index,Object element):在指定位置处添加一个新的元素
    删除功能:
		Object remove(int index):删除角标对应的元素
    获取功能:
		Object get(int index):获取指定位置处的元素
      	int size():获取集合的元素数
        Object set(int index,Object element):在指定位置处使用当前元素element元素替换
    ListIterator<E> listIterator();List集合的专有遍历方式
    ListIterator:列表迭代器
    ListIterator<E> listIterator():这个方法底层实现:是通过ArrayList里面的成员内部类
    ListItr extends Itr:实现的
正向遍历
    booean hasNext();判断是否有下一个元素
    Object next();获取下一个元素
逆向遍历
    boolean hasPrevious();判断是否有上一个元素
    Object previous():获取前一个元素
List集合的遍历方式:
	1)Collection集合的方法 Object[] toArray
	2)Collection集合的迭代器Iterator iterator()
	3)size()+Object get(int index):普通for循环
	4)列表迭代器:ListIteraotr listiterator()
	
	
	并发:指的是在一个时间点上同时发生!
 	并行:指的是在一个时间段内同时发生!
 	
 	解决方案:
 * 		1)要么使用迭代器遍历元素,使用迭代器添加元素!
 * 		2)要么集合遍历遍历元素,使用集合添加
这个学生类中,如果要进行自然排序(测试类中:通过TreeSet()创建对象),这个类必须实现接口:Comparable
TreeSet集合:
 * 		本质基于TreeMap的底层实现(红黑树结构---->自平衡"的二叉树结构")
 * 	有两种排序方式:
 * 		自然排序
 * 		选择器排序
 * 
 * 取决于创建当前Set集合对象的时候的构造方法
 * public TreeSet():默认的自然顺序排序
 * 
 * TreeSet<Integer>
 * 
 * 由于TreeSet属于Set集合(本身保证元素唯一,不重复的元素!),还可以将元素按照自然顺序排序
无参构造方法:自然排序
有参构造方法:选择排序

Map集合

java.util.Map<K,V>:接口
Java提供了集合:双列集合
 * 键:K 学号:String "班级+学号id"		键的特点:必须唯一的!
 * 值:V	 学生Student
 Map集合的特点: 一个键值对元素(一个键对应一个值,值是可以重复,但是键必须唯一)  
 * 			只针对键有效,跟值无关!	(看成是:夫妻对)
 * Map<String,Student>
 * 
 * 学生学号			学生的姓名
 * 		1			马伊琍
 * 		2			李四
 * 		3			王五
 * 		1			姚笛
	Map和Collection集合的区别?
 * 	Map<K key,V value>集合:双列集合,键映射到值的对象 ,键必须保证唯一,可以看成是一个(夫妻对)
 * 					遍历方式和Collection集合遍历方式不同
 *  Collection<E>集合:
单列集合:只能存储一种引用类型,里面的set集合依赖于Map集合的实现 (理解为:光棍)
 *  			HashSet---->HashMap里面put方法
 *  			TreeSet---->TreeMap里面的put方法
 * Map集合的功能:
 * 			添加功能
 * 			V put(K key, V value) :添加一个键值对元素
 * 					问题:返回值是什么意思 
 * 				/如果当前键是一次存储的时候,返回的结果null
				//如果键是不是第一次存储,后面重复,将当前对应的值把以前的值覆盖掉并保存下来,返回以前的值!

刪除功能:

  •  	V remove(Object key):刪除指定的键,返回的是跟键关联的值,如果没有映射关系,则返回null
    
  •  	void clear():删除全部的键以及值
    
  •  	判断功能
    
  •  	boolean containsKey(Object key):是否包含指定的键
    
  •  	boolean containsValue(Object value):是否包含指定的值
    
  •  	boolean isEmpty():判断Map集合是否为空
    
  •  	高级功能:
    
  •  	Set<K> keySet():获取所有的键的集合
    
  •  	V get(Object key):通过键获取对应的值
    
  •  	Set<Map.Entry<K,V>> entrySet():获取当前Map集合中所有的键值对对象
    
  •  	K getKey() :通过键值对对象获取键
    
  •  	V getValue():通过键值对对象获取值
    

HashMap<K,V>是Map集合的子实现类,里面哈希表结构,保证(键唯一)

  • Map集合只只针对键有效

  • HashMap<Integer,String>键:Integer

  • HashMap<String,Student> :键:String

  • HashMap<Student,String>:键是自定义对象

  • keySet():获取Map集合的所有的键

    面试题:
     * 		TreeSet集合存储自定义类型,什么情况下自然排序(Comparable),什么情况下是选择器排序(Comparator)?
     * 
     * 		执行无参构造方法:TreeSet<Student>():无参构造----是自然排序:
     * 	要求当前自定义类型需要实现Comparable接口,重写comparesTo方法
     * 		
     * 		执行有参构造方法:TreeSet<Student>(Comparator<Student> com):
     * 			方式1:自定义一个类实现Comparator接口中 的compare(T t1,T t2)方法
     * 			方式2:通过接口匿名内部类实现
    

    晨写

    1.List集合三个子实现类的特点
    ArrayList:底层数据结构是数组,查询快,增删慢
    从线程角度:线程不安全的,不同步的-----执行效率高!
    Vector:
    底层数据结构是数组,查询快,增删慢
    线程角度:线程安全----同步的------执行效率低(可变因子)
    LinkedList
    底层数据结构是链接列表,查询慢,增删快
    线程角度:线程不安全的----不同步的-----执行效率高!

    2.HashSet集合存储自定义对象如何去重
    不重复的,能够保证元素唯一,不能保证迭代顺序恒久不变!
    HashSet
    HashSet的添加功能add---->HashMap集合put方法
    hashCode()和equals方法

     			对于自定义对象所在的类必须重写hashCode()和equals方法()
     						
     	HashSet<String>
    

    3.List集合存储自定义对象如何去重
    本身:可重复的,存储和取出一致
    List
    使用新集合的思想:使用新集合判断元素是否包含在该集合中!
    contains()方法---->底层依赖于equals方法()

     List<Student>:自定义对象所在类重写equals()方法/重写hashCode()
    

    4.集合和数组,StringBuffer的区别?
    三者都是容器
    StringBuffer:存储的可变的字符序列(构造字符串缓冲区),最终是以"字符串"展示
    线程角度:是一个线程安全的,同步----执行效率低---->单线程程序中,使用StringBuilder替代StringBuffer

    集合:单例集合(Collection)
    长度可变,可以存储任意类型的元素,它只能引用数类型
    数组:
    长度固定同一种类型的元素,它可以存储基本类型/引用类型

    应用场景:大部分时候会使用集合去操作!
    查询所有/查询一些部分数据----存储到集合中List

    5.目前集合的遍历方式有几种,列举即可
    Collection集合的遍历方式
    List

     		5种:
     				Object[] toArray
     				Collection的迭代器:Iterator iterator()
     				List列表迭代器:ListIterator listiterator()
     				size()和get(int index)相结合,普通for循环
     				增强for循环:替代迭代器,简化书写格式:foreach语句 (推荐)
    

    6.final,finalize的区别?
    final:状态修饰符,修饰类,该类不能被继承
    修饰变量,此时变量是常量
    修饰成员方法,该方法不能被重写
    finalize:是Object类中方法,主要用来开启垃圾回收器,会调用finalize()方法,回收没有更多引用
    的对象(和GC有关系!)

1.List集合遍历的方式
4种方式:
Object[] toArray()
Collection集合的迭代器:Iterator iterator()
List的特有功能:
Object get(int index)+size() 相结合:for循环
ListIterator listiterator():列表迭代器

2.泛型的好处是什么,以及格式
<引用数据类型>,可以用在类上,方法上,接口上…
好处:
1)避免了强制类型转换
2)将运行时期异常提前到了编译时期
3)解决了黄色警告线问题
4)提高了程序的安全性

3.匿名内部类的本质
本质:继承了该抽象类或者实现了接口的子类对象!
格式
new 类名(具体类名/抽象类名)/接口名(){
重写抽象方法;
} ;

4.this和super的区别
this:代表当前类对象的地址值引用
super:代表父类的空间标识(父类对象的地址值引用)

	访问构造方法
		this():访问本类的无参构造方法
		this(xxx):访问的是本类的有参构造
		
		super():访问父类的无参构造方法
		super(xxx):访问的是父类的有参构造
	成员方法:
			this.方法名():访问的是本类的成员方法
			super.方法名():访问的是父类的成员方法
	成员变量:
			this.变量名:本类的成员变量
			super.变量名:父类的成员变量

5.面向对象的三大特征
封装,继承,多态(重点)
接口多态:使用最多:接口名指向子实现类名
抽象类多态:(其次)IO流中 抽象类名指向子类名 :InputStream in = new FileInputStream(“xxx.txt”)

1Map集合的遍历方式

方式1:
	Set<K> keySet():获取所有键的集合
	V get(Object key):通过键获取值
方式2:
	Set<Map.Entry<K,V>>
	entySet():通过map集合对象获取键值对对象的集合
	K getKey():通过键值对对象获取键
	V getValue():通过键值对对象获取值
	
	
	
	public List<Product> findAll(){}
	返回值:后台获取List列表----->前后端技术List---->传递到前台(json串)
	需要在前台页面中展示所有列表数据--->将json串里面获取到遍历!
	

2.获取字节码文件的方式

目前有两种
	Object类中的getClass()方法,任意Java类型的class属性
	
	Class.forName("类的全限定名称")

3.List集合遍历的方式

五种
	Object[] toArray();
	Iterator iterator();
	ListIterator listiterator();
	size()+get(int index)结合的普通for
	增强for:
		for(集合储存数据类型 变量名:集合对象){
		使用变量名....
		}
	

4.Collection和Map集合的区别

Collection集合
	Collection<E>:单例集合
			它里面有两个子接口List   Set:集合即可是重复的(有序的),也可以不重复(无序的)
			Collection集合它的子实现类关联Map集合的子实现类相关方法
	Map<K,V>:双列集合针对键有效,跟值无关(键:必须唯一,值可以重复)
		HashMap<K,V>
		TreeMap<K,V>

5.TreeSet集合针对自定义对象的 时候什么时候是自然排序,什么情况下是选择器排序

无参构造方法:TreeSet<自定义类型>():自然排序
	条件:自定类必须实现一个接口:Comparable<T>重写public int comparTo(T t){}方法
有参构造方法:TreeSet<自定类型>(Comparator<T> com)
	方式1:
					自定义一个类:实现Comparator接口,重写接口中compar(T t1,T t2)方法
				方式2
					直接使用接口 匿名内部类来实现
				TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>(){
								public int compare(Student s1,Student s2){
									....
								}
				
				}) ;


1.TreeSet集合存储自定义对象并按某种方式排序

按照主要条件进行排序!

自然排序
选择器排序


无参构造方法:TreeSet<自定义类型>():自然排序
		条件:自定类必须实现一个接口:Comparable<T> 重写public int comparTo(T t){}方法
		
	有参构造方法:
			TreeSet<自定类型>(Comparator<T> com)
				方式1:
					自定义一个类:实现Comparator接口,重写接口中compar(T t1,T t2)方法
				方式2
					直接使用接口 匿名内部类来实现
				TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>(){
								public int compare(Student s1,Student s2){
									....
								}
				
				}) ;

2.Map集合的遍历方式

		方式1:
				Set<K> keySet() :获取所有键的集合
				V get(Object key):通过键获取值
		
		方式2:
				Set<Map.Entry<K,V>> entySet():通过map集合对象获取键值对对象的集合
				K getKey():通过键值对对象获取键
				V getValue():通过键值对对象获取值

3.Collections

针对集合操作工具类:
    public static  void sort(List<T> list):针对List集合自然排序
    public static void sort(List<T> list,Comparator<T> com):针对:List集合进行比较器排序
    max()
    min()

1. 模拟斗地主洗牌和发牌

场景1:不保证牌有序的 ArrayList集合:牌盒

package com.luoliang.Arraylist_1;

import java.util.ArrayList;
import java.util.Collections;

public class CollectionsTest {
	public static void main(String[] args) {
		//创建一个牌盒ArrayList
		ArrayList<String> array=new ArrayList<String>();
		//装牌
		/*
		 * 两个数组: 点数数数组 A 2 3 4 5 6 7 8 9 10 J Q K 花色数组:♥ ♠ ♣ ♦
		 */
		// 定义点数数组
		String number[]= {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
		String[] colors= {"♥", "♠", "♣", "♦"};
		// 2.1)将点数数组遍历,并且同时将花色数组遍历
		// 将点数和花色拼接起来(String类型:concat())
		//遍历
		for(String num : number) {
			for(String col:colors) {
				String poker=col.concat(num);// 2.2)需要将牌添加到ArrayList集合 牌盒中
				array.add(poker);
				

			}
		}
		//储存大王小王
		array.add("大王");
		array.add("小王");
		//3)洗牌
		//Collections的静态功能:随机置换
		Collections.shuffle(array);
		//三个玩家
		/**
		 * 三个玩家---->每一个玩家 看成以"集合" ArrayList

 * 创建三个集合,存储对应自己的牌

 * 创建一个集合:ArrayList---存储底牌:3张

 * A,B,C三个人

 * A--B---C ---A---B---C

 * 遍历牌盒

 * for(int x = 0  ; x < array.size(); x ++){

 * //3个玩

 * //规律

 * 取底牌

 * 如果

 * x>=array.size()-3    

 * 获取底牌get(int index)

 * 如果x % 3 == 0 

 * 获取第一个玩家的牌

 * x% 3 == 1

 * 获取第二个玩家的牌

 * x% 3 == 2

 * 获取第三个玩家的牌

 * }
   	 */
   	ArrayList<String>  player1 = new ArrayList<String>() ;
   	ArrayList<String>  player2 = new ArrayList<String>() ;
   	ArrayList<String>  player3 = new ArrayList<String>() ;
   	ArrayList<String>  diPai = new ArrayList<String>() ;//它这个地方是给每个人还有底牌创建一个新的arraylist集合;记住
   	for(int x=0;x<array.size();x++) {
   		//判断是否是底牌
   		//判断三种情况
   		if(x>=array.size()-3) {
   			//底牌
   			diPai.add(array.get(x));
   			// List中get(int index)---获取集合中元素
   		}else if(x%3==0) {
   			//玩家1
   			player1.add(array.get(x)) ;
   		}else if(x%3==1) {
   			//玩家2
   			player2.add(array.get(x)) ;
   		}else if(x % 3 == 2) {
   			//玩家3
   			player3.add(array.get(x)) ;
   		}
   	}
   	

   	/**
   	 * 看牌
   	 * 		玩家1,玩家2,玩家3  , 同时还向看底牌
   	 */
   	lookPoker("农民", player1);
   	lookPoker("农民", player2);
   	lookPoker("地主", player3);
   	lookPoker("底牌", diPai);

   }

   private static void lookPoker(String name, ArrayList<String> array) {

   	// TODO Auto-generated method stub
   	System.out.print(name+"的牌是:");
   	for(String s:array) {
   		System.out.print(s+" ");
   	}
   	System.out.println();

   }
   }

场景2:洗牌和发牌 ,发到每个人的手上,牌是有序的!



package com.luoliang.Arraylist_1;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
/**

 * 模拟斗斗地主洗牌和发牌,并且保证每个人手上的有序!

 * 

 * 分析:

 * 1)创建牌盒

 * HashMap<Integer,String> 

 * 键存储的是牌的编号

 * 值存储的是就是每一个牌(花色和点数的拼接)

 * ArrayList<Integer>

 * 单独存储编号

 * 

 * 2)装牌		

 * 定义一个编号:int index = 0 ;

 * 定义花色字符串数组:♥ ♠ ♣ ♦

 * 点数字符串数组     3 4 5 6 7 8 9 10 J Q k A 2

 * 

 * 2.1)遍历点数数组和花色数组,拼接起来

 * 2.2)给HashMap<Integer,String> 存储编号和牌

 * 给ArrayList存储编号

 * index ++

 * 

 * 2.3)给HashMap<Integer,String>单独存储小王,和大王

 * 给ArrayList<Integer>添加小王对应的编号 并index++

 * 

 * 

 * 3)洗牌					

 * 洗 的是编号:

 * Collections

 * public static void shuffle(List<?> list):随机置换

 * 

 * 4)发牌

 * 发的也是编号,为了保证每个人手上的有序,所以三个玩家都需要TreeSet<Integer>

 * for(int x = 0  ; x < array.size(); x ++){

 * //3个玩

 * //规律

 * 取底牌

 * 如果

 * x>=array.size()-3    

 * 获取底牌get(int index)

 * 如果x % 3 == 0 

 * 获取第一个玩家存储的编号

 * x% 3 == 1

 * 获取第二个玩家存储的编号

 * x% 3 == 2

 * 获取第三个玩家的编号

 * }

 * 

 * 

 * 5)看牌

 * 封装成一个功能

 * lookPoker(String name,TreeSet<Integer> ts,HashMap<Integer,String> hm)

 * 

 * 遍历TreeSet集合:获取每一个手上的编号

 * 在使用编号在hm集合寻找对应的值: get(K key)--->V value

 * 输出牌即可!

 * 

 * 

 * 

 * 

 * @author zhangyang
   *
    */
   public class CollectionsTest2 {
   public static void main(String[] args) {
   	HashMap<Integer,String> hash=new HashMap<Integer,String>();
   	ArrayList<Integer> array=new ArrayList<Integer>();
   	//装牌
   	String[] number= {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
   	String[] color= {"♥", "♠", "♣", "♦"};
   	

   	//编号从零开始
   	int index=0;
   	//遍历点数数组和花色数组,拼接起来
   	for(String num:number) {
   		for(String col:color) {
   			//拼接
   			String poker=col.concat(num);//concat是拼接的意思
   			//将编号以及牌添加HashMap集合中
   			hash.put(index,poker);//他的意思就是说吧牌号和编号添加进来
   			//将编号存储在ArrayList集合中
   			array.add(index);
   			index++;
   		}
   	}
   	//储存小王
   	hash.put(index,"小王");
   	//将小王存储在ArrayList集合中
   	array.add(index);
   	index++;
   	//储存大王
   	hash.put(index,"大王");
   	//将大王编号存储在ArrayList集合中
   	array.add(index) ;
   	
   	//测试
   	//洗牌,洗的是牌号
   	Collections.shuffle(array);//shuffle()该方法是打乱顺序
   	//发牌
   	//发的也是编号,为了保证每个人手上的有序,所以三个玩家都需要TreeSet<Integer>
   	/**
   	 * for(int x=0;x<array.size();x++){
   	 * 		x>=array.size()-3
   	 * 		获取底牌get(int index)
   	 * 
   	 * 		如果x%3==0;//%取余
   	 * 		获取第一个玩家储存的编号
   	 * 
   	 * 		x%3==1;
   	 * 		获取第二个玩家存储的编号
   	 * 
   	 * 		x% 3 == 2
   	 * 		获取第三个玩家的编号
   	 * }
   	 * 
   	 * */
   	TreeSet<Integer> player1=new TreeSet<Integer>();
   	TreeSet<Integer> player2=new TreeSet<Integer>();
   	TreeSet<Integer> player3=new TreeSet<Integer>();
   	TreeSet<Integer> dipai=new TreeSet<Integer>();
   	//判断底牌以及三种情况
   	for(int x=0;x<array.size();x++) {
   		//判断底牌以及三种情况
   		if(x>=array.size()-3) {
   			dipai.add(array.get(x));
   		}else if(x%3==0) {
   			//玩家1
   			player1.add(array.get(x)) ;
   		}else if(x %3  ==1) {
   			//玩家2
   			player2.add(array.get(x)) ;
   			
   		}else if(x % 3 == 2) {
   			//玩家3
   			player3.add(array.get(x)) ;
   		
   		}
   		
   	}
   	//看牌
   	//将看牌封装成功能
   	//单独调用
   	lookpoker("地主",player1,hash);
   	lookpoker("农民",player2,hash);
   	lookpoker("农民",player3,hash);
   	lookpoker("底牌",dipai,hash);}
   '''
   private static void lookpoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hash) {
   	

   	System.out.println(name+"的牌是");
   	//需要遍历TreeSet集合获取每一个手上的编号
   	for(Integer key:ts) {
   		//获取到了每一个编号
   		//在HashMap集合中:通过键获取值:获取的牌
   		String value=hash.get(key);
   		System.out.print(value+" ");
   		
   	}
   	System.out.println();//换行
   	}

    	}
    	

异常的处理方案有那些

1)try…catch…finally:标准格式 捕获异常

2)throws:抛出异常(抛出到方法上)

方式1:捕获异常的变形格式

​ try…catch…

​ try…catch…catch…

​ try…finally…(线程中:Lock锁)

  • 格式:流程

    • try{
      •   		...
        
      •   		...
        
      •   		可能出现问题代码
        
      •   		}catch(异常类名 变量名){//具体异常的类
        
      •   		//处理异常
        
      •   		//自己手动处理
        

/**

​ 如果使用try…catch…catch…catch…

  • 那么后面的catch语句中的异常类要么是同级关系要么是前面异常的类父类!
    */

关于Throwable中的一些方法

  • public String getMessage():获取异常的消息字符串
  • public String toString():获取异常信息的简述描述
  • 异常的全限定名称:包名.类名:调用该异常对象的getMessage()详细的消息字符串
  • public void printStacktrace():将此对象的信息追踪到堆栈中,具体获取到具体源码中那一块处问题了

针对异常处理的另一种方式:

throws:抛出异常

​ 抛出在方法声明上,如果方法中的语句体现了异常,将异常交给jvm,jvm将异常信息输出到控制台上

面试题
throws和throw的区别
	throws:抛出
		书写位置在声明上
		throws的后面跟的异常类名,而且可以跟多个异常类名,中间使用逗号隔开
		对于throws它是由调用者进行处理,必须要对带throws的方法进行处理
		throws表示抛出异常的一种肯定性(这个方法可能出现问题/可能没有问题)
	throw:抛出
		书写位置在方法体中
		throw的后面跟的异常对象,一般都是匿名对象new XXXExceptioon();而且只能跟一个异常对象
		由方法中逻辑判断进行处理(由方法体中语句进行处理)
		throw:表示抛出异常一种肯定性(执行到逻辑的时候,一定会执行这个异常!)
		

自定义的异常!

  • 1)自定义一个类,继承自Exception或者RuntimeException
  • 2)提供无参构造方法 /有参构造 传递String参数(消息字符串)
异常的注意事项:
  • 1)子类继承父类的时候,对父类的成员方法进行重写,如果父类的成员方法有异常
  • 那么子类的该方法针对异常处理,要么是跟父类的异常类名一致,要么是父类异常类的子类
  • 2)子类继承父类重写父类的方法的时候
  • 父类的成员方法没有抛出异常,子类的该方法不能抛出异常,只能try…catch…
面试题
  •  如果捕获异常的时候,
    
  •  try...catch...finally,catch中如果有return语句,那么finally中的代码还会执行吗?
    
  •  在return之前执行还是return之后执行
    
  •  会执行,除非Jvm退出了不执行!
    
  •  return 之前		
    
1.什么是进程,什么是线程?
  • 进程:分配?调度系统资源的基本单元,在执行过程产生一跟实例!
  • 线程:是进程的执行流,进程中的某个任务

2.线程的实现方式1的步骤

关于多线程方式1:

  • 自定义一个类继承自Thread类
  • 重写Thread类中的run方法
  • 在mian方法中创建当前线程类对象,启动线程start()启动

3.异常的处理方式有几种

两种

  • 显示处理
  • throws:抛出异常(为了操作方便)
  • try…catch…finally:捕获异常,开发中,建议是这个方式

4.throw和thows的区别

throws

  • 跟在方法声明上
  • throws的后面跟的是异常类名,可以跟多个异常类名,中间使用逗号隔开
  • throws抛出的异常:由调用者进行处理 (必须要对带有throws的方法进行处理!)
  • throws抛出:表达的存在异常的可能性!

throws

  • 在方法语句中
  • throw后面跟的是异常对象,格式throw new XXException(),只能跟一个异常对象(匿名对象)
  • throw抛出异常的处理---->由逻辑语句进行处理(if…else…)
  • throw抛出:是存在异常的肯定性!

5.什么是finally

​ final,finalize
​ 异常的处理:捕获异常的标准格式
​ try{
​ …
​ }catch(异常类名 对象名){
​ …
​ }finally{
​ //在释放相关的系统资源 ,这里面代码一定会执行 (除非:在执行finally语句之前jvm退出了!)
​ }

6.启动线程为什么是start而不是run方法

start()启动是通过jvm调用run方法,run方法调用只是普通方法!
start()底层是通过---public natvie....

2.异常类

Throwable
         error :严重问题
         		以后:微服务的分布式项目中:内存溢出... 
         Exception:可以通过一些处理方式进行解决
         		编译时期异常:当前本身jdk提供的方法自带处理异常,必须解决!
         		运行时期异常RuntimeException:代码逻辑不够严谨导致的!
异常的处理
		显示处理
				throws:抛出异常 (为了操作方便)
				try...catch...finally:捕获异常 	开发中,建议是这个方式

4.多线程的引入

				1)自定义一个类继承自Thread类
				2)重写Thread类中的run方法
				3)在main方法中创建当前线程类对象,启动线程 start()启动

3.线程的状态有几种呢? 6种

4.多线程的实现方式2:接口: Runnable

5. 多线程实现方式1和实现方式2对比

代理:---------->Java中一种设计模式
   静态代理
   动态代理
   	JDK动态代理
   	CGLib动态代理

java能够开启线程吗?

Java不能够直接开启线程的!

start方法方法—通过JVM调用

start方法本身就是同步方法----线程安全的方法

  • 将所有的开启的线程(在运行之前),将线程添加到线程组中:ThreadGroup:一个线程组中包含多个线程
  • 调用start0():间接实现的
  • 本地方法----C++语言实现 !

public final void setDaemon(boolean on):设置守护线程

在启动线程之前,调用这个方法才能设置为守护线程 (注意事项!)

  • (如果当前运行中线程都是守护线程,JVM退出)

如何获取主线程中名称呢?

  • public static Thread currentThread():表示当前正在运行的线程
  • getName():获取线程名称
  • setName(String name):设置当前线程名称

public final void join() throws InterruptedException:等待该线程终止

public final void setPriority(int newPriority)

  • 设置线程的优先级
  • public final int getPriority():获取线程的优先级
  • 线程的优先级: 常量值
  • public static final int MAX_PRIORITY:最大优先级 10
  • public static final int MIN_PRIORITY:最小优先级 1
  • public static final int NORM_PRIORITY:默认优先级 5
  • 优先级越大的线程抢占CPU的执行权几率大
  • 优先级越小的线程抢占CPU的执行几率小
  • 符号线程的执行具有随机性

public static void sleep(long millis) throws InterruptedException

  • 线程睡眠 (阻塞式方法!)
  • 参数为时间毫秒值!

线程的生命周期/线程的状态

  • State:线程的状态:是Thread类内部枚举

  • public enum State {

    NEW, 线程新建状态 ---->public static final…

    RUNNABLE,线程运行状态

    BLOCKED,线程阻塞状态(sleep(),等待)

    WAITING,//死死等待

    TIMED_WAITING,//超时等待 等待到一定时间,不等了

    TERMINATED;//线程终止!
    }

@Deprecated:JDK提供内置注解:标记方法是否以过时!

  • public final void stop():已过时的方法,但是可以使用!强迫线程停止执行
  • public void interrupt():中断线程 :中断线程的一种状态!(6种状态),
  • 打破了状态之后,继续执行程序!

public static void yield():暂停当前正在执行的线程对象,并执行其他线程!

  •  理解为"谦让"
    
  •  线程的执行随机性
    

多线程的实现方式2(推荐)

  • 1)自定义一个类(资源类),这个类实现接口:Runnable接口—用到了Java设计模式之代理模式!
  • 2)重写Runnable接口中的run方法
  • 3)在主线程中main
  • 3.1)创建当前资源类对象,
  • 3.2)在创建Thread类对象,将3.2中的资源类对象作为参数进行传递
  • 4)启动线程 start方法启动

方式1:
1)自定义一个类MyThread,继承自 Thread
2)重写Thread类中run方法
3)在main中,创建该线程类对象

MyThread my1  = new MyThread() ;
MyThread my2  = new MyThread() ;
MyThread my3  = new MyThread() ;
my1.start();
my2.start() ;
my3.start() ;

my1,my2在并发的执行

继承关系的弊端:
		局限性

它不能够体现出"数据共享"的概念!

	电影卖票:100张票 三个窗口
	
	每一个窗口可能都在卖自己的100张票
	线程的执行	"随机性"
	原子性操作:
		100张: 变量tickets    (tickets--)  100 --- 99
	
栈内存										堆内存
	MyThread my1					new MyThread() ;
	
	MyThread my2					new MyThread() ;


​ MyThread my3 new MyThread() ;




第二种方式
​ 优势:静态代理

​ 能够体现出 “资源共享”

	1)自定义一类MyRunnable  implements Runnable
	2)重写run方法
	3)创建资源类对象,创建线程类对象,将资源类对象当做参数传递
	
	MyRunnable my = new MyRunnable() ;


// public Thread(Runnable target, String name) :创建线程类对象并同时给线程设置名称
​ Thread t1 = new Thread(my, “窗口1”) ;
​ Thread t2 = new Thread(my, “窗口2”) ;
​ Thread t3 = new Thread(my, “窗口3”) ;
​ //启动线程
​ t1.start();
​ t2.start();
​ t3.start();


​ 栈内存中 堆内存中

		Thread t1				new Thread(0x01)    Thread(Runnable runable)
		
		Thread t2				....
		
		Thread t3				...
		
		MyRunnable my(0x01)	------>		  new MyRunnable() 

package com.luoliang.Thread_4;

public class SellTicket implements Runnable {
		//成员位置定义门票100张:共享
	private   int piao = 100 ;
	Demo d=new Demo();
	Object obj=new Object();
		public void run() {
			while(true) {
				/**
				 * synchronized(锁对象){ //门的开/关		
				 * 	锁:可以是任意Java类对象(Object或者任意的子类)
				 *  多条语句对共享数据进行操作
				 * }
				 */
				synchronized(d) {	
					if(piao>0) {
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
					// TODO Auto-generated catch block
							e.printStackTrace();
						}
						System.out.println(Thread.currentThread().getName()+"正在出售第"+(piao--)+"张门票");
						}else {
							System.out.println("同志,没有票了,记得早点来...");
							break;
						}
					piao--;
				}
			
			}
		}
}	
		class Demo{}
	
	
	package com.luoliang.Thread_4;

public class SellTicketDemo {
	public static void main(String[] args) {
				//创建资源类对象
				SellTicket st=new SellTicket();
				//创建线程类对象	
				
				Thread st1=new Thread(st,"窗口1");
				Thread st2=new Thread(st,"窗口2");
				Thread st3=new Thread(st,"窗口3");
				Thread st4=new Thread(st,"窗口4");
				//启动线程
				st1.start();
				st2.start();
				st3.start();
				st4.start();
	}
}
package com.luoliang.Thread_3;

public class SellTicket extends Thread{
		//成员位置定义门票100张:共享
		private static int piao = 100 ;
		@Override
		public void run() {
			while(true) {
			if(piao>0) {
				try {
					Thread.sleep(300);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(getName()+"正在出售第"+(piao--)+"张门票");
			}
			
			}
		}	
}
package com.luoliang.Thread_3;

public class SellTicketDemo {
	public static void main(String[] args) {
		//创建线程类对象
				SellTicket st1 = new SellTicket() ;
				SellTicket st2 = new SellTicket() ;
				SellTicket st3 = new SellTicket() ;
				
				//设置线程名称
				st1.setName("窗口1");
				st2.setName("窗口2");
				st3.setName("窗口3");
				
				//启动线程
				st1.start();
				st2.start();
				st3.start();
	}
}

1.多线程中相关的一些方法

线程的优先级:priority 	
setPriority(int a)
最大优先级:10
最小优先级:1
默认优先级:5

sleep(long time) throws InterruptedException:参数为时间毫秒值,
休眠指定的时间;睡眠的过程中,线程暂停执行的状态
stop():过时了,强迫线程停止执行
interrupt():中断线程的一种状态


join():等待该线程终止!
			底层依赖于 wait(long time),参数为0,等待状态:WATTING
									参数为整数,到底一定时间,等待结束!
			 wait(long time):Object类中方法 (本地方法实现)
	
	yield():暂定当前正在执行的线程,执行其他线程  "谦让"

2.电影院卖票—引入多线程的安全问题

能够体现数据共享---实现方式2
加入延迟操作:睡眠一定时间
同票
负票

解决方案:引入同步代码块 
  synchronized(锁对象){} ----能够解决安全问题---可能造成死锁!

锁对象:理解为门的"开和关"
锁对象必须是多个线程使用同一个锁对象!


1.同步方法的引入

2.死锁一种现象----如何解决

3.死锁引入----等待唤醒机制(生产消费者模式)

4.jdk5以后提供一种锁:可重入锁:Lock (java.util.concurrent:JUC(包))

具体的功能:
  获取锁/释放锁

5.线程组(了解) ThreadGroup

6.线程池(ExecutorService—Executors的静态功能)

创建线程池
提交异步任务--->Callable接口  重写的call()方法

7.线程中匿名内部类的方式

1.多线程实现方式1和方式2的步骤

多线程实现方式1)
		1)自定义一个类,继承自 extends Thread
		2)重写Thread类中的run方法-----实质是本质调用Runnable接口的run
		3)创建当前线程类对象 
			启动线程
			
多线程的实现方式2)
		1)自定义一个类,实现Runnable接口 :implements Runnable
		2)重写Runnable接口的run方法
		3)创建当前资源类对象
			然后创建Thread类对象,将资源类对象作为参数进行传递(资源类被共享)

2.什么是静态代理
代理角色:帮助真实角色完成一些事情,对真实角色的功能进行增强!
真实角色:专注于自己的事情

特点:真实角色和代理角色都需要实现接口   举例:MyRunnable(自定义的类)/Thread类 实现 Runnable接口

3.join()和yield()方法的区别
join():等待该线程终止!
底层依赖于 wait(long time),参数为0,等待状态:WATTING
参数为整数,到底一定时间,等待结束!
wait(long time):Object类中方法 (本地方法实现)

yield():暂定当前正在执行的线程,执行其他线程  "谦让"

4.Java能够开启线程吗?
不能直接开启

	线程对象.start()
				start0():本地方法	public native void start0().

5.线程的状态有几种 6种
Thread$State(枚举)

	NEW	,	新建
	RUNNABLE, 执行
	BLOCKED , 阻塞
	WATTING ,:等待状态:一直等待
	TIMED_WAITED,:超时等待 :wait(long time):正数 时间到了,等待结束! sleep(long time)  join()
	TERMINATED ; :线程终止(死亡)

6.校验多线安全问题的标准是什么,如何解决这种问题?
1)当前是否是多线程环境
2)是否有共享数据
3)是否存在多条语句对共享数据进行操作

解决方案:同步机制 
关键字:
同步代码块---解决线程安全问题
锁对象:可以是任意Java类对象			Object obj = new Object();
synchronized(锁对象){
		将多条语句对共享数据的操作包裹起来;
}


​ 同步方法:非静态的 锁对象:this
​ 方法声明上加入一个synchronized

package com.luoliang.homework4;
//插入排序
public class ArrayDemo {
	public static void main(String[] args) {
		//创建一个数组,静态初始化
		int[] arr= {6,5,8,4,7};
		//排序前
		System.out.println("排序前");
		printArray(arr);
		insertSort(arr);
		System.out.println("排序后");
		printArray(arr);
	}

	private static void insertSort(int[] arr) {
		// TODO Auto-generated method stub
		for(int x=1;x<arr.length;x++) {
			for(int y=x;y>0;y--) {
				if(arr[y]<arr[y-1]) {
				int temp=arr[y];
				arr[y]=arr[y-1];
				arr[y-1]=temp;
				}else {
				// 如果当前arr[y]> arr[y-1] 比较结束
				break;
				}
			}
		}
	}

	private static void printArray(int[] arr) {
		// TODO Auto-generated method stub
		System.out.print("[");
		for(int x=0;x<arr.length;x++) {
			if(x==arr.length-1) {
				System.out.println(arr[x]+"]");
				
			}else {
				System.out.print(arr[x]+",");
			}
		}
	}	
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值