Java List集合和Object类

List集合和Object类

1. List集合

1.1 List集合概述
List集合
	特征:
		有序 添加顺序和存储顺序一致
		可重复 允许出现相同元素
	三个常用实现类:
		ArrayList[最常用] LinkedList Vector
1.2 List集合涉及到的方法
增
	add(E e);
		添加当前创建List集合约束类型的元素,到集合末尾。
	add(int index, E e);
		在List集合指定下标位置,添加符合类型的元素
	addAll(Collection<? extends E> c);
		添加参数集合到当前集合的末尾,要求参数集合存储元素类型为当前约束类型或者其子类
	addAll(int index, Collection<? extends E> c);
		在指定下标位置,添加参数集合到当前集合,要求参数集合存储元素类型为当前约束类型或者其子类
	
删
	E remove(int index);
		删除指定下标的元素,返回值是被删除的元素内容
	remove(Objec obj);
		在List集合中删除指定元素
	removeAll(Collection<?> c);
		删除两个集合的交集
	retainAll(Collection<?> c);
		保留两个集合的交集
	clear();
		清空整个集合
	
改
	E set(int index, E e);
		使用符合类型的元素,替换指定下标元素,返回值是被替换的元素对象
查
	int size();
		当前集合有效元素个数
	boolean isEmpty();
		判断当前集合是否为空
	boolean contains(Object obj);
		判断指定元素是否存在
	boolean containsAll(Collection<?> c);
		判断指定集合是否为当前集合的子集合
    Object[] toArray();
    	获取当前集合所有元素的Object类型数组    
    int indexOf(Object obj);
    	获取指定元素在集合中第一次出现的下标位置
    int lastIndexOf(Objec obj);
    	获取指定元素在集合中最后一次出现的下标位置
    E get(int index);
    	获取集合中指定下标元素
    List<E> subList(int fromIndex, int endIndex);
    	获取当前集合的子集合,要求从fromIndex开始,到endIndex结束。要头不要尾
1.3 代码演示
package com.qfedu.a_list;

import java.util.ArrayList;
import java.util.List;

/**
 * List接口常用方法
 * @author 期年之前ying@
 *
 */
public class Demo2 {
    
    
	public static void main(String[] args) {
    
    
		List<String> list1 = new ArrayList<String>();
		
		list1.add("张三");
		list1.add("李四");
		list1.add("王五");
		list1.add("");
		list1.add("华中路京广路交叉口向东200m 老北京炸酱面");
		list1.add("大骨头");
		
		System.out.println(list1);
		
		list1.add(1, "湖南牛肉米粉");
		System.out.println(list1);
		
		List<String> list2 = new ArrayList<String>();
		list2.add("沙县小吃");
		list2.add("兰州拉面");
		list2.add("黄焖鸡米饭");
		
		list1.addAll(3, list2);
		System.out.println(list1);
		
		String string = list1.remove(5);
		System.out.println(string);
		System.out.println(list1);
		
		String str = list1.set(3, "糖醋鲤鱼");
		
		System.out.println(str);
		System.out.println(list1);
		
		System.out.println(list1.get(6));
		
		System.out.println(list1.indexOf("大骨头"));
		System.out.println(list1.lastIndexOf("大骨头"));
		
		List<String> subList = list1.subList(2, 5);
		System.out.println(subList);		
	}
}
1.4 ArrayList 可变长数组【重点】
1.4.1 ArrayList概述
	ArrayList底层采用数组形式进行数据保存和处理。底层数组为Object类型,可以存储任意类型数据。存储对应具体数据类型通过创建ArrayList类对象约束,因为所有的添加操作都是通过该add和addAll方法完成的。
	可变长数组是通过grow方法来进行底层数组容量扩容操作。扩容比例大约是原数组的1.5倍
	ArrayList特征:【重点】
		增删慢,查询快
	特有方法:	
		可以使用所有的List集合对应方法。
		了解两个特殊方法:
			trimToSize();
				当前底层数组容量缩小至有效元素个数,节约内存空间。时间换空间 
			ensureCapacity(int capacity);
				判断当前容量是否满足需求
/**                                                              
 * Increases the capacity to ensure that it can hold at least the
 * number of elements specified by the minimum capacity argument.
 *                                                               
 * @param minCapacity the desired minimum capacity               
 */                                                              
private void grow(int minCapacity) {
    
                                 
    // elementData是底层Object数组,用于数据存储,所谓的原数组                               
    int oldCapacity = elementData.length;                        
    int newCapacity = oldCapacity + (oldCapacity >> 1);          
    if (newCapacity - minCapacity < 0)                           
        newCapacity = minCapacity;                               
    if (newCapacity - MAX_ARRAY_SIZE > 0)                        
        newCapacity = hugeCapacity(minCapacity);                 
    // minCapacity is usually close to size, so this is a win:   
    // 1. 创建新数组,2. copy原数据 3. 返回新数组地址
    elementData = Arrays.copyOf(elementData, newCapacity);       
}                                                                
1.4.2 特征分析
增删慢:
	增加慢:
		1, 有可能触发扩容操作。在扩容方法操作中,从原数组拷贝数据到新数组浪费时间,同时在扩容操作会出现无效内
		存销毁问题,同样浪费时间。
		2. 插入数据到指定下标位置,从插入位置开始,数组中的其他数据会整体向后移动。移动操作浪费时间。
	删除慢:
		1. 删除指定下标元素,数组中的元素整体向前移动。
		2. 删除元素较多情况下,会导致空间冗余。空间效率较低
		
查询快:
	【寻址操作】
	ArrayList底层数据操作方式为数组方式,数组+下标获取对应元素的操作效率是非常高!!!是CPU根据对应【地址】直接访问操作。
1.4.3 【补充知识点 地址到底是什么】
开发中经常听说的地址到底是什么?
	内存编号
	内存中最小单位是【字节】,计算机按照每一个字节空间,进行编号操作。每一个字节都有一个独一无二的编号。
	例如:
		8GB内存,内存地址编号范围
		8,589,934,592 编号总值,计算机中很多数据都是从0开始
		范围:
			0 ~ 8,589,934,591 
			计算机中所有的地址都是 十六进制展示方式 0x0 ~ 0x1 FFFF FFFF

null 是什么???
	null ==> 0x0 内存中编号为0的字节空间,该字节空间受系统保护,任何程序不得读取或者写入数据到当前字节空间中。如果操作直接发送计算机最高权限命令 kill -9 
	null 一般用于引用数据类型变量初始化操作。如果出现了NullPointerException都是因为null地址空间读取或者写入操作。
	NullPointerException问题 向刘不配提问 需要在QQ群发普通拼手气红包50元RMB
1.4.4 【补充知识点 数组内存地址分析图】

在这里插入图片描述

1.5 LinkedList 双向链表
1.5.1 双向链表

在这里插入图片描述

1.5.2 LinkedList常用方法
其他方法都是List集合规定方法:
	
addFirst(E e);
	添加元素到链表头
addLast(E e);
	添加元素到链表尾 ==> add(E e);
E removeFisrt();
	删除链表头元素,返回值是被删除元素
E removeLast();
	删除链表尾元素,返回值是被删除元素
E getFirst();
	获取链表头元素
E getLast();
	获取链表尾元素

队列:
	先进先出,排队!!!
	addLast(E e);
	E getFirst();
	E removeFirst();
堆栈:
	先进后出,弹夹!!!
	addFirst(E e);
	E getFirst();
	E removeFirst();
package com.qfedu.a_list;

import java.util.LinkedList;

/*
 * LinkedList集合
 */
public class Demo3 {
    
    
	public static void main(String[] args) {
    
    
		LinkedList<String> list = new LinkedList<String>();
		
		list.add("唐人街");
		list.add("你好,李焕英");
		list.add("流浪地球");
		list.add("战狼2");
		list.add("人在囧途");
		
		list.addLast("湄公河行动");
		list.addFirst("魔童降世");
		
		String first = list.getFirst();
		String last = list.getLast();
		
		String removeFirst = list.removeFirst();
		String removeLast = list.removeLast();
		
		System.out.println(list);
		
		System.out.println(first);
		System.out.println(last);
		System.out.println(removeFirst);
		System.out.println(removeLast);
	}
}

2. Object类

2.1 Object类概述
Object是Java中所有类的基类,万物都是Object。
	Object规定了每一个的唯一标记:
		hashCode方法
	比较方式 
		equals方法
	字符串期望方法
		String toString();
		
	线程操作相关方法:
		notify
		notifyAll
		wait
2.2 equals方法重写
boolean equals(Object obj);
	是Object类内规定的两个对象比较使用方法,如果两个对象为同一个对象,返回true,否则返回false
	【默认方式】
		比较参数对象和调用方法对象的空间首地址。
		地址相同的两个对象,一定是同一个对象。
/*                                                                  
 * 重写equals流程/内容                                                    
 * 1. 原则不变,地址相同的两个对象为同一个对象,返回true                                   
 * 2. 参数类型和当前调用方法的数据类型一致!!!【数据类型判断】                                 
 * 3. 比较两个对象中数据元素                                                   
 */                                                                 
@Override                                                           
public boolean equals(Object obj) {
    
                                     
	// 1. 原则不变,地址相同的两个对象为同一个对象,返回true                               
	if (this == obj) {
    
                                                  
		return true;                                                
	}                                                               
	                                                                
	/*                                                              
	 *  2. 参数类型和当前调用方法的数据类型一致!!!【数据类型判断】                            
	 *  instanceof 关键字                                              
	 *  	obj instanceof Person                                   
	 *  	判断obj对应的数据到底是不是Person类型。是返回true,否则返回false               
	 */                                                             
	if (!(obj instanceof Person)) {
    
                                     
		return false;                                               
	}                                                               
	                                                                
	/*                                                              
	 * 3. 比较两个对象中数据元素                                               
	 * 当前参数对象通过以上两步验证,可以明确不是同地址对象,同时和当前方法调用对象类型一致。       
	 * 可以明确obj引用数据类型指向的数据是一个Person对象。参数对象目前对外数据效果为Object            
	 * 类型。我们需要拔掉衣服看本质,【强制类型转换】                                      
	 */                                                             
	Person p = (Person) obj;                                        
	                                                                
	return this.id == p.id                                          
			/*                                                      
			 * this.name.equals(p.name)                             
			 * 该equals方法为String类型equals方法,也是重写Object类内的equals完成     
			 * 为了满足字符串比较使用。                                         
			 *                                                      
			 * 字符串比较绝对不允许使用 ==                                      
			 *                                                      
			 * 【必须明确每一个方法的执行者到底是谁!!!】                               
			 */                                                     
			&& this.name.equals(p.name)                             
			&& this.age == p.age;                                   
}                                                                   
2.3 hashCode方法重写
Java中的规定
	两个对象通过equals方法比较结果为true,要求hashCode结果一致。
在Object类内
	hashCode方法返回值数据是当前对象在内存空间中的地址十进制数据
@Override                                                
public int hashCode() {
    
                                      
	/*                                                   
	 * Objects工具类方法                                      
	 * int hash(Object... values);                       
	 * 		... 不定长参数,要求当前参数的类型为Object类型,参数个数不限制。        
	 * 		不定长参数在方法内实际上是一个数组形式                          
	 * 		Object... ==> 方法内就是一个Object[]                
	 *                                                   
	 * hash方法可以将当前给予方法的参数进行hash计算,得到一个hash值。             
	 * 这里要求参与equals方法比较的成员变量,全部放入到hash方法中进行              
	 * 哈希值获取操作。                                          
	 */                                                  
	return Objects.hash(id, name, age);                  
}                                                        
 * hash方法可以将当前给予方法的参数进行hash计算,得到一个hash值。             
 * 这里要求参与equals方法比较的成员变量,全部放入到hash方法中进行              
 * 哈希值获取操作。                                          
 */                                                  
return Objects.hash(id, name, age);                  

}

猜你喜欢

转载自blog.csdn.net/lsq736158497/article/details/114147873