Java集合整理

一.集合

  1. 引入集合

    集合和数组的比较
    集合和数组的相似点
    都可以存储多个对象,对外作为一个整体存在
    数组的缺点
    长度必须是在初始化的时候指定 而且固定不变

    集合框架:
    集合框架使用方便的接口和类 它们位于java.util包中,存放在集合中的数据,被叫元素(element)
    容器的分类图
    集合框架:
    Collection接口存储一组不唯一,无序的对象
    List接口存储一组不唯一,有序(索引顺序)的对象
    Set接口存储一组唯一,无序的对象
    Map接口存储一组键值对象,提供Key和value的映射
    key唯一 无序
    value 不唯一,无序的

二.List集合

List集合主要的实现类有ArrayList和LinkedList,分别是数据结构中的顺序结构表额链表的实现

		List:
			特点 :有序的  不唯一(可重复)
		
		ArrayList:
			在内存中分配连续的空间,实现长裤可变的数组 (顺序表结构)
			优点:遍历元素和随机访问元素的效果比较高
			缺点:添加和删除需要大量的元素移动效率低,按照内容查询效率低
			
		顺序图
		
		LinkedList:
			采用双向链表存储方式 
			缺点:遍历和随机访问元素效率低
			优点:插入.删除元素效率高(但是前提是先低效率查询才可,如果插入删除发生在头尾可以减少查询的次数)
			
		双向链表
		
	Arraylist使用:
public class TestArrayList {
			public static void main(String[] args) {
				//创建一个ArrayList对象
				ArrayList<Integer> list = new ArrayList();
				//向集合中添加多分数
				list.add(78);//加到最后
				list.add(89);
				list.add(59);
				list.add(89);
				list.add(2,50);//加到指定位置,底层发生了大量的元素后移
				ArrayList list2 = new ArrayList();
				list2.add(20);//加到最后
				list2.add(60);
				list2.add(99);
				list1.addAll(0,list2);
				System.out.println(list.size());
				System.out.println(list);

					//遍历元素
					//方法1:使用for循环
					for (int i = 0; i <list.size() ; i++) {
						//获取第i个元素
						int elem = list.get(i);
						//输出第i个元素
						System.out.println(i+"    "+elem);
					}
					//方法2:使用增城的for循环
					for (Object   elem:list) {
						System.out.println(elem);
					}
					//方法3 Iteratorx使用迭代器
					Iterator<Integer> it  = list.iterator();
					while (it.hasNext()){//还有元素,没有元素就结束循环
						//如果有,就取出来
						int elem = it.next();
						//输出
						System.out.println(elem);
					}
				}
			}
			
			类的方法
			
		ArrayList底层就是一个长度可以动态增长的Object数组;在JDK1.7中无参数构造方法创建ArrayList对象是,默认长度是10,
		在JDK1.8 中使用无参数购房者方法创建ArrayList对象,默认数组长度是0 第一次添加元素,容量不足就要进行扩容
		
		
		LinkedList的使用
			public class TestLinkedayList {
				public static void main(String[] args) {
					//创建一个LinkedList对象
					List<Integer> list = new LinkedList();
					//向集合中添加多分数
					list.add(78);//加到最后
					list.add(89);
					list.add(59);
					list.add(89);//自动封装
					list.add(new Integer(78));
					list.add(2,50);//加到指定位置,底层发生了大量的元素后移
					ArrayList list2 = new ArrayList();
					list2.add(20);//加到最后
					list2.add(60);
					list2.add(99);
					list.addAll(0,list2);
					System.out.println(list.size());//元素个数
					System.out.println(list);
					list.remove(1);//删除索引1的内容
					System.out.println(list);
					System.out.println(list.isEmpty());
					//遍历元素
					//方法1:使用for循环
					for (int i = 0; i <list.size() ; i++) {
						//获取第i个元素
						int elem = list.get(i);
						//输出第i个元素
						System.out.println(i+"    "+elem);
					}
					//方法2:使用增城的for循环
					for (Object   elem:list) {
						System.out.println(elem);
					}
					//方法3 Iteratorx使用迭代器
					Iterator<Integer> it  = list.iterator();
					while (it.hasNext()){//还有元素,没有元素就结束循环
						//如果有,就取出来
						int elem = it.next();
						//输出
						System.out.println(elem);
					}
				}
			}
		将ArrayList替换成LinkedList之后不变
			运算结果没有变
			执行结果的功能代码没有变
		ArrayList替换成LinkedList之后变化
			底层结构变了 
			ArrayList是数组  LinkedList 双向链表
		具体的执行过程变化了list.add(2,99)//在指定位置添加元素
			ArrayList:大量的后移元素
			LinkedList:不需要大量的移动元素,修改节点的指向就可以
		使用那个会更好
			根据使用场合来定
			大量的根据索引查询操作,大量的遍历操作(按照索引0-n-1逐个查询般),建议使用ArrayList
			如果存在较多的添加,删除操作建议使用LinkedList
		LinkedList增加了那些方法
			增加了对添加.删除.获取首位元素的方法
			addFirst();   addLast();  removeFirst();  removeLast(); getFirst();  getLast();
			
			
	LinkedList的底层是一个双向链表,实现了Deque接口   所以除了可以作为线性表来使用,还可以当做队列和栈来使用
	
Deque和Queue的实现类
	1.ArrayDeque  顺序栈   数组
	2.LinkedList 链栈  链表
	
理解java中栈和队列的接口的实现类
public class TestLinkedList2 {
			public static void main(String[] args) {
				//摞盘子
				Deque<String >deque1 = new LinkedList<>();
				deque1.push("盘子1");
				deque1.push("盘子2");
				deque1.push("盘子3");

				System.out.println(deque1.size());
				System.out.println(deque1.peek());
				System.out.println(deque1.peek());
				while(!deque1.isEmpty()){
					String elem = deque1.pop();
					System.out.println(elem);
				}
				System.out.println(deque1.size());
			}
		}

三. Set集合的使用
Set:
t特点:无序 唯一的(不重复)

	HashSet
		采用Hashtable哈希表存储结构
		优点:添加速度快  查询速度快,删除速度快
		缺点:无序
		
	LinkedHashSet
		采用哈希表存储结构,同时使用链表维护次序
		有序(添加顺序)
		
	TreeSet
		采用二叉树(红黑树)的存储结构
		优点:有序 查询速度比List快(按照内容查询)
		缺点:查询速度没有HashSet快
使用各种Set集合类存储课程名称
		public class TestSet1 {
			public static void main(String[] args) {
				//创建一个集合Set对象
			   // Set<String > set = new HashSet<>();
				//Set<String> set = new LinkedHashSet<>();
				Set<String> set = new TreeSet<>();
				//添加多个课程
				set.add("java");
				set.add("Otacle");
				set.add("HTML");
				//输出课程
				System.out.println(set.size());
				System.out.println(set);
				//不可以使用for循环变量set
				/*for (int i = 0; i <set.size() ; i++) {
					set.get(i);
				}*/
				//支持增强的for循环
				for (String elem:set
					 ) {
					System.out.println(elem);
				}
				//支持Iterator
				Iterator<String> it = set.iterator();
				while (it.hasNext()){
					System.out.println(it.next());
				}
			}
		}
		
总结:
	HashSet 哈希表  唯一的  无序的
	LinkedHashSet  哈希表+链表   唯一  有序的 (添加顺序)
	TreeSet 红黑树 一种二叉平衡树  唯一的 有序的  (自然顺序)
	List针对Collection增加了一些关于索引位置的操作的方法get(i)
		add(i,elem),remove(i),set(i,ele,)
	Set是无序的,不可能提供关于索引位置操作的方法,set针对Collection没有增加任何方法
	List的遍历方式   for循环,for-eacch循环  Iterator迭代器   流失编程 forEach
	Set的遍历方式    for- each循环    Iterator迭代器    流式编程 forEach
	
	
HashSet LinkedHashSet 需要类实现hashCode()和equals();
TreeSet 需要类实现 Comparable接口并指定比较规则

四.哈希表
哈希表的结构和特点
hashtable 也叫散列表,特点快 很快 神奇的快
结构 结构有很多种 最流行的最容易理解 顺序表+链表
主要结构:顺序表每个顺序表的节点在一个单独引出一个链表
哈希表是如何添加数据的
计算哈希 码(调用hashCode(),结果是一个int值,整数的哈希码取自身即可)
计算在哈希表中的存储位置 y=k(x)=x%元素长度
x:哈希码 k(x) 函数y:在哈希表中的存储位置
存入哈希表
情况1:一次添加成功
情况2:多次添加成功(出现了冲突,调用equals()和对应链表的元素进行比较,比较到最后,结果都是false,创建新节点,存储数据,并加入链表末尾)
情况3:不添加(出现了冲突,调用equals()和对应链表的元素进行比较, 经过一次或者多次比较后,结果是true,表明重复,不添加)
结论1:哈希表添加数据快(3步即可,不考虑冲突)
结论2:唯一、无序

哈希表是如何查询数据的
	和添加数据的过程是相同的
	  情况1  一次找到
	  情况2 多次找到
	  情况3 找不到
	  哈希表查询数据块
	 
hashCode和equals有什么作用
	HashCode();计算哈希码,是一个整数,根据哈希码可以计算出数据在哈希表中的存储位置
	equals();  添加时出现了冲突, 徐亚通过equals进行比较,判断是否相同查询时也需要使用equals();进行比较,判断是否相等
	
如何减少冲突 
	哈希表的长度和表中的记录数的比例--装填因子: 
		如果Hash表的空间远远大于最后实际存储的记录个数,则造成了很大的空间浪费, 如果选取小了的话,则容易造成冲突。 在实际情况中,一般需要根据最终记录存储个数和关键字的分布特点来确定Hash表的大小。还有一种情况时可能事先不知道最终需要存储的记录个数,则需要动态维护Hash表的容量,此时可能需要重新计算Hash地址。 
	   装填因子=表中的记录数/哈希表的长度, 4/ 16  =0.25   8/ 16=0.5 
	如果装填因子越小,表明表中还有很多的空单元,则添加发生冲突的可能性越小;而装填因子越大,则发生冲突的可能性就越大,在查找时所耗费的时间就越多。 有相关文献证明当装填因子在0.5左右时候,Hash性能能够达到最优。 
	因此,一般情况下,装填因子取经验值0.5。 
   哈希函数的选择 
		 直接定址法    平方取中法  折叠法   除留取余法(y = x%11) 
   处理冲突的方法 
		  链地址法  开放地址法  再散列法   建立一个公共溢出区 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值