内部类-集合-常用类

内部类

	*内部类的访问特点
		*内部类可以直接访问外部类的成员,包括私有
		*外部类要访问内部类的成员,必须创建对象
		//内部类和外部类没有继承关系
	
	*成员内部类怎么创建对象
		*格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
		*举例:Outer.Inner oi = new Outer().new Inner();

	*局部内部类
		*内部类在局部位置
		*方法的内部  内部类的下面(因为代码在方法中是按顺序执行的)

	*匿名内部类
		*概念
			匿名:没有名字
			一个没有名字的内部类

		*格式:
			*格式:new 类名 ( ) {  重写方法 }    //这里的类既可以是普通类也可以是抽象类
				  new  接口名 ( ) { 重写方法 }
				举例: new Inter(){
					  @Override
					  public void method(){}
				} 
			*匿名内部类的本质
				本质:是一个继承了该类或者实现了该接口的子类匿名 "对象"   //名字叫匿名内部类,但是真正得到的是一个对象
		*匿名内部类的格式推导
			匿名内部类是为了简化  "局部内部类"   
			
		*匿名内部类的转变过程
			单独的实现类文件------------>内部类--------------->匿名内部类
			
		*匿名内部类的使用场景
			//特点是只能使用一次  +   本质是一个对象
			当需要的类型是一个类、接口的时候,并且只使用一次

冒泡排序

	*冒泡排序的原理
		(1)每一轮比较下来能得到一个最大值
		(2)一共需要比较n-1轮
		(3)已经确定了位置的数,不需要再次进行比较

	*代码实现
		public class MaoPao {
				public static void main(String[] args) {
					int[] ints = {13, 85, 56, 32, 75};
					for (int i = 0; i < ints.length - 1; i++) {    //这里的-1是因为n个数据只需要比较n-1轮
						for (int j = 0; j < ints.length - 1 - i; j++) {   //这里的-1是因为为了防止数组越界    -i是已经确定了位置的数不需要再参与比较
							if (ints[j] > ints[j + 1]) {
								int temp = ints[j];
								ints[j] = ints[j + 1];
								ints[j + 1] = temp;
							}
						}
					}
					for (int i = 0; i < ints.length; i++) {   //遍历元素
						System.out.println(ints[i]);
					}
				}
			}

Arrays数组工具类

	用来操作数组的工具
	*static String toString?(int[] a) 返回指定数组的内容的字符串表示形式。
		//就是用来替代for循环遍历数组的
		for (int i = 0; i < ints.length; i++) {
			System.out.println(ints[i]);
		}
		等价于
		System.out.println(Arrays.toString(ints));
		
	*static void sort?(int[] a) 按照数字顺序排列指定的数组 
		//就是用来替代冒泡排序的
			例如:Arrays.sort(ints);
			
	*工具类
		*工具类所在的包名必须使用util或者utils结尾
		*工具类的类名必须以util或者utils结尾
		*构造方法必须私有
		*所有的方法必须是静态的

包装类

	*将基本数据类型包装成一个类

	*为什么要使用包装类
		*可包装一些咱们记不住的数据
		*为集合做铺垫   //主要功能
	
  *基本类型和对应包装类
	  基本数据类型            对应的包装类
		byte  ------------  	Byte
		short -------------     Short
		int   --------------    Integer   //注意
		long  --------------    Long
		char  --------------    Character  //注意
		boolean  -----------    Boolean
		float   ------------    Float
		double  ------------    Double
	
	*Integer类
		*软件包  java.lang 
			使用的时候不需要导包
			
		*继承体系
			java.lang.Object 
				java.lang.Number 
					java.lang.Integer 

		*成员变量   
			static int MAX_VALUE 保持最大值一个 int可以有2 31 -1。 
				System.out.println(Integer.MAX_VALUE);
			static int MIN_VALUE 持有最小值的常数为 int可以为-2 31 。  
				System.out.println(Integer.MIN_VALUE);
		
		*构造方法  
			(1)Integer(int value) 已过时。
				很少使用这个构造函数。 静态工厂valueOf(int)通常是一个更好的选择,因为它可能产生明显更好的空间和时间性能。  
					Integer i1  = new  Intyeger(100);
			(2)Integer(String s) 已过时。 将String转成Integer
				很少使用这个构造函数。 使用parseInt(String)将字符串转换为int原语,或使用valueOf(String)将字符串转换为Integer对象。  
					参数String的要求是必须是纯数字的     NumberFormatException:数字转换异常
					Integer i1  = new  Intyeger("100");
					
			重要:构造方法是可以进行数据类型转换的
		
    *int和String的相互转换
		*int------------>String
			 (1)使用int类型的数据+""
				举例: String s1 = 100+"";   
			(2)String类的valueOf(int i)
				static String valueOf?(int i) 返回 int参数的字符串表示形式。  
				举例: 
					String s = String.valueOf(100);   //较为规范
					
		*String------->int 
			(1)static int parseInt?(String s) 将字符串参数解析为带符号的十进制整数。
				举例: 
					int i = Integer.parseInt("123");

日期类

		*常用方法 
			(1)long getTime?() 返回自1970年1月1日以来,由 Date对象表示的00:00:00 GMT的毫秒数。    
				    Date---------->毫秒值
					返回值:指的是毫秒值
					
					 Date d2 = new Date();
					long time = d2.getTime();
			(2)void setTime?(long time) 将此 Date对象设置为1970年1月1日00:00:00 GMT后的 time毫秒的时间点。   
					毫秒值-------->Date类型 
					参数:毫秒值
					 Date d3 = new Date();
					d3.setTime(1000*60*60);
					System.out.println(d3);
					
		*重点掌握Date与String的互相转换
			*格式化方法
			String format?(Date date) 将日期格式化成日期/时间字符串 
				代码实现:
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					String format(Date date) 将日期格式化成日期/时间字符串
					String format = sdf.format(d2);
					System.out.println(format);
		
			应用场景:转成前台页面想要的格式展示出来   好处:就是可以转成我们想要的格式
		
			String ---------- > Date
			*解析方法
				Date parse?(String source) 从给定字符串的开始解析文本以生成日期。 
					代码实现:
						Date parse = sdf.parse("2019-12-25 18:41:20");
						System.out.println(parse);
						
				应用场景:将String类型的时间字符串转成Date类型后,可以使用里面的getTime()得到毫秒值,做差值计算

异常

	*Throwable 异常的根类
	*Error  错误  / / / (内存溢出)  / / / 栈内存溢出
	*Exception  异常
			*编译期异常(非RuntimeException)
			*运行期异常(RuntimeException)
	
	*处理方式
		*try------catch
			catch中的异常必须是try中代码运行会产生的异常,否则将无法进行捕捉
		*try------catch-----finally
		*throws  直接将异常进行抛出,暂时不进行处理
		
	*编译时异常和运行时异常的区别
		(1)编译时异常 
			*执行javac命令时出现的异常
			*特点是在idea中会以红色波浪线的形式体现出来,不处理就无法执行
			
		(2)运行时异常
			*执行java命令时出现的异常
			*特点是在idea中不会有红色波浪线的提示,只有在运行时才会出现
	
	*为什么要区分编译期异常和运行期异常?
		针对的角色不一样
			1.运行期异常
				针对于用户,也就是说运行期异常是由用户产生的。
				但是用户产生的问题我们开发人员要去解决,给出一个友好的提示。

			2.编译期异常 
				针对于开发人员

集合 (collection)

	*常用方法
		boolean add(E e) 添加元素   //重要     在末尾添加
	
		boolean remove(Object o) 从集合中移除指定的元素    //重要    根据元素来删
			//删除的是从0索引开始出现的第一个该元素
			
		void clear() 清空集合中的元素  //高危操作 
		
		boolean contains(Object o) 判断集合中是否存在指定的元素    //很容易忘记
			//弊端:虽然知道有没有这个元素,但是却不知道具体的位置
		
		boolean isEmpty() 判断集合是否为空 
	
		int size() 集合的长度,也就是集合中元素的个数  //相对重要
	
	*集合的判空
				什么叫判空?判断该容器不为空
				什么叫空?  这里的空有两层含义,一个是为null,集合的元素数量为0
				if(null!=collection && collection.size()>0){
					xxxxxxxxxxxxxxxxx
				}
				
	*length、length()、size()三者的区别?
				length:数组的长度  是一个属性
				length():字符串的长度  是一个方法
				size():是集合的长度  是一个方法			
				
	*遍历	
		*为什么要使用迭代器而不是普通for循环来遍历Collection
		因为Collection集合有一个子接口是Set,Set集合没有索引,所以使用普通for循环就不能得到每一个元素
		
		*使用迭代器遍历元素的步骤
			(1)获取迭代器对象  iterator
			(2)循环获取每一个元素
				hasNext()
					//在这里有一个类似于指针的东西,初始位置在元素的最上方
					判断有没有下一个元素
					
				next()
					*获取了下一个值
					*取完值之后把指针向下移动一位
			//注意:不用多次使用next()方法
	*分类
		*单列集合(list/set)
		*双列集合(map)

list集合

	*特点
		*元素可重复
		*存取有序
		*有索引
	
	*List集合的  "特有"   方法
		void add(int index,E element) 在此集合中的指定位置插入指定的元素 //在指定的索引位置
		E remove(int index) 删除指定索引处的元素,返回被删除的元素   //根据索引删除   
		E set(int index,E element) 修改指定索引处的元素,返回被修改的元素   //重要
		E get(int index) 返回指定索引处的元素   //重要
		//(1)List集合特有方法中有一个共同点,参数都有索引
	
	/删除List集合中的指定元素
			两种思想:
				(1).新建一个集合,然后遍历要操作的集合,把符合要求的添加到新的集合中
				(2).在原有的集合上进行遍历,把需要删除的元素直接删掉
				//面试题:怎么删除List集合中指定元素?
					"反向遍历"
	
	*列表迭代器
		(1)列表迭代器是List集合对象的
			list.listIterator();
			
		(2)列表迭代器的特有方法
			*void add?(E e) 将指定的元素插入列表(可选操作)。  
			*boolean hasPrevious?() 如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回 true 。 
				判断有没有前一个元素
				
			*E previous?() 返回列表中的上一个元素,并向后移动光标位置。 
				获取上一个元素的值
				将光标向上移动一位
		注意事项:
			(1)列表迭代器的add方法和List集合的add方法有什么区别?
				*列表迭代器的add方法是在当前指针的后面添加
				*集合的add方法是在末尾添加
		
			(2)hasPrevious?和previous?的弊端
				前提:需要先将指针正向遍历到末尾
				原因:因为指针的默认初始化位置在元素的最上方
	
	*增强for循环
		(1)格式
			for(元素的类型 变量名 : 数组或者集合对象){
				xxxxx
			}
		
		(2)本质
			底层代码其实就是迭代器,出现增强for循环的原因就是为了简化迭代器的格式
		
		(3)注意事项
			使用前要进行判空
				List<Student> c1 = null;
					for (Student stu : c1) {    //会出现空指针
						System.out.println(stu);
					}
		
	总结:List集合遍历的方式
		第一种:迭代器遍历集合对象
		第二种:普通for循环(因为list集合有索引)   //需要修改集合中的元素
		第三种:增强for循环   //遍历  不修改集合中的元素
		
	*List集合的实现类的特点
		ArrayList 
			底层结构是数组
			查询快、增删慢
			线程不安全的、效率高
		
		LinkedList 
			底层结构是链表
			查询慢、增删快 
			线程不安全的、效率高
		
		Vector
			底层结构是数组
			查询快、增删慢
			线程安全的、效率低	
			
	*总结:目前而言都用ArrayList
		重点掌握:
			增
			删
			改
			遍历
			判空		

并发修改异常

		并:并行  同时
		发:发生
		
		*条件一:并发:同时发生  (至少需要两个对象)
		*条件二:修改:修改元素
		//产生并发修改异常的条件就是上面两个同时发生
			 Iterator<Student> iterator = c.iterator();
				while (iterator.hasNext()){
					c.add(s1);
					Student s = iterator.next();
					System.out.println(s);
				}
			上面代码产生并发修改异常的原因?
				条件一: 有两个对象同时在操作集合  一个对象是iterator,还有一个对象是集合对象c
				条件二:集合对象这个方法c.add(s1),修改了集合中的元素
			就产生了并发修改异常	

Set集合

	*特点
		*唯一
			数据不可重复
		*没有索引
			不能使用普通for循环进行遍历
		*存取无序
	
	*遍历
		*迭代器
		*增强for循环
		
	*实现类HashSet集合的特点
		*和Set集合的特点一毛一样
		*底层结构是哈希表(数组+链表)
	
	*Set集合是怎么保证元素唯一性的(为什么要重写hashCode和equals方法?)
		依赖了hashCode和equals方法
		(1)先计算hashCode值
			*哈希表中还没有这个哈希值
				直接将元素添加到set集合中
			*哈希表中已经存在了这个哈希值
		(2)将要添加的元素使用equals和该哈希值下面的“桶”中的每一个元素进行比较
				  *如果桶中已经有这个元素了,覆盖
				  *如果桶中没有,添加进来
	*什么时候重写hashCode和equals方法? 
			*保证唯一性
			*需要比较的是对象的属性
		
	*LinkedHashSet
		*底层结构是哈希表和链表组成
		*特点
			唯一: 由哈希表保证
			存取有序:链表保证
		*应用场景
			去重

	*TreeSet集合
		*特点
			(1)唯一
			(2)有序(按照一定的规则排序)  //注意
			(3)不带索引
	
		*排序方式
			(1)自然排序
				*要求:
				第一个:创建TreeSet集合的时候,构造方法不能有参数
					//TreeSet<Student> ts = new TreeSet<Student>();
				
				第二个:创建TreeSet集合时的泛型类(就是尖括号里面的类TreeSet<Student>)
				需要实现Comparable接口,重写comparaTo方法
					public class Student implements Comparable<Student> {  
						
						public int compareTo(Student s) {
							// return 0;
							// return 1;
							// return -1;
							//按照年龄从小到大排序
							int num = this.age - s.age;
							// int num = s.age - this.age;
							//年龄相同时,按照姓名的字母顺序排序
							int num2 = num==0?this.name.compareTo(s.name):num;
							return num2;
							}
					}
		
		
		(2)比较器排序
			*要求:
				第一个:创建TreeSet集合的时候,构造方法要传入一个Comparator接口类型变量
					//TreeSet<Student> ts = new TreeSet<Student>(Comparator对象);
					
					//代码实现:  
						public class ComImpl1 implements Comparator<Student> {   //传入的比较规则
								@Override
								public int compare(Student s1, Student s2) {
									int num = s1.getAge()-s2.getAge();
									if (num == 0){
										int i = s1.getName().compareTo(s2.getName());
										num = i;
									}
									return num;
								}
							}

					public class Demo1 {
							public static void main(String[] args) {
								ComImpl1 c1 = new ComImpl1();
								TreeSet<Student> ts = new TreeSet<>(c1);

								Student s1 = new Student("王小二",12);
								Student s2 = new Student("王小三",13);
								Student s3 = new Student("王小四",12);
								Student s4 = new Student("王小五",15);
								Student s5 = new Student("王小六",13);
								Student s6 = new Student("王小七",18);

								ts.add(s1);
								ts.add(s2);
								ts.add(s3);
								ts.add(s4);
								ts.add(s5);
								ts.add(s6);

								System.out.println(ts);
							}
						}

		(1)通用性
			自然排序: 
				弊端:对于使用的是API自动帮我们重写的comparaTo方法,默认按照字典顺序,如果我们想改变排序规则是不能改代码的,比如String我们想要按照字符串的长度比较
			比较器排序:   //推荐使用
				好处:在一定程度上解了耦合
				TreeSet<Student> ts = new TreeSet<>(c1);

可变参数

	*当我们在定义方法的时候,不知道有多少个参数的时候,可以考虑使用可变参数
	*格式
		修饰符  返回值  方法名(数据类型... 变量名){
		xxxxx
		
	}
	例如: 
		public static void show(int... a){
					System.out.println(a);
				}

	*本质
		可变参数的本质是一个数组
		定义数组:  int[]  ints ;
		可变参数:int... a;
			//可变参数中的int 相当于于定义数组时(int[]  a)前面的数据类型int 相当于定义数组时数组的名称  (重要)
	*注意事项
		如果一个方法有多个参数,包含可变参数,可变参数要放在最后

Map集合

	*Map集合的特点
			键值对映射关系
			一个键对应一个值
			键不能重复(Set),值可以重复(Collection)
			元素存取无序
	
	*Map集合的基本功能 
		V put(K key,V value) 添加元素    //不是add
		V remove(Object key) 根据键删除键值对元素
			//根据key删除的是   键值对
		void clear() 移除所有的键值对元素
		boolean containsKey(Object key) 判断集合是否包含指定的键
		boolean containsValue(Object value) 判断集合是否包含指定的值
		boolean isEmpty() 判断集合是否为空
		int size() 集合的长度,也就是集合中键值对的个数

	*Map集合的获取功能
		V get(Object key) 根据键获取值
			//变相的说明了key和value之间是有对应关系的
		Set keySet() 获取所有键的集合
			//为什么返回值是一个set集合?
				//因为Map集合的key特点是唯一、存取无序,和Set集合的特点一样
	
		Collection values() 获取所有值的集合
			//为什么返回值是Collection
				//因为value的值是根据key值来的,没有什么特殊的要求
		
		Set<Map.Entry<K,V>> entrySet() 获取所有键值对对象的集合
			//entry是条目的意思,这里指的是一条记录  其实就是一个键值对
		
		
		注意事项:
			map集合本身没有迭代器的概念

	*Map集合最重要的方法
		增:
			V put(K key,V value) 添加元素
		删:
			V remove(Object key) 根据键删除键值对元素
		改:
			V put(K key,V value) 添加元素   //注意:当key值存在的时候,put方法就是修改,   key值不存在put方法就是添加
		遍历
			1.遍历方式一
			遍历的步骤
				(1)获取所有的key集合
				(2)循环遍历每一个key
				(3)根据每一个key去获取对应的value
				(4)打印出key---value的对应关系
			
			2.遍历方式二
				遍历步骤
					(1)获取所有键值对的集合
					(2)循环遍历键值对集合,得到每一个键值对对象
					(3)获取key和value
						key:getKey()
						value:getValue()
					(4)打印出key---value的对应关系
			
	*什么时候要重写hashCode和equals方法?
		(1)自定义对象
		(2)自定义对象需要保证唯一的时候
				*hashset存储自定义对象
				*TreeSet集合存储自定义对象
				*LinkedHashSet存储自定义对象
				*Map集合的key存储自定义对象

	*斗地主案例的实现

File类

	*概念
	是文件和目录路径名的抽象表示   //目录和文件两个都可以用File类来表示

	*注意事项
	我给的那个路径,不是一定要真实存在的,所以创建出来的File对象可能是真实存在的,也可能是不存在的

	*相对路径和绝对路径的问题   
		相对路径:一般情况下,不带盘符的就是相对路径
				//相对于谁?
					//相对于当前的项目(project),而不是模块(module),它和模块是平级的关系
				
		绝对路径:一般情况下,带盘符的就是绝对路径
				//"d:\\abc"

递归

		*概念
			递归指的是"方法"定义中"调用方法本身"的现象   //方法自己调用自己的现象
			
		*递归的两个条件
			(1)递归一定要有出口
				转化成代码:既然有出口就一定要进行判断是不是出口
					if(是否是出口){
					}
				
			(2)要有方法自己调用自己的现象  //需要我们找的就是这个规律
				show(){
					xxxx
					show()
				}
		*总结:
				public 返回值  方法名(参数列表 变量名){
					if(是出口){
						return  返回值;
					}else{
						return  方法名();  //规律自己找
					}
				}
					
			
		*注意事项
			(1)递归一定要有出口。否则内存溢出
			(2)递归虽然有出口,但是递归的次数也不宜过多。否则内存溢出

		*关于递归的总结
			不管是自己写递归方法还是看人家的递归代码
				*出口的判断
				*方法自己调用自己的规律
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值