有容乃大--Java 集合(List/Set/Map)

集合框架

集合框架: 看成是学习一些Java中设计好的容器(装东西的)类;

  1. 如何创建容器对象;
  2. 如何把数据装到容器中—》 调用方法;
  3. 如何把容器中的数据取出—>还是调用方法;

下面是集合的整体框架图
在这里插入图片描述

List

ArrayList
语法特点

  1. 内部基于数组实现的一个集合类。查询比较快,添加和删除相对比较慢
  2. 猜ArrayList中会有哪些功能(方法): 添加、删除、查询、插入、修改。。。
  3. 不是同步的(存在线程安全问题),如何解决:敬请期待… 用Vector

基本使用

  1. 参考api一个一个写
  2. 三个构造函数
  3. 增删改查
  4. 数组和List相互转化

遍历方式

  1. 使用普通的for循环
    ArrayList bag = new ArrayList();
    bag.add("电脑");
    bag.add(200);
    bag.add("鼠标");
    bag.add("小人书");
    bag.add("教材");
    bag.add("牛奶");
    		
    for(int i=0;i<bag.size();i++){
    	System.out.println(bag.get(i));
    }
  1. 增强for循环(foreach)
    语法:
	for(源中的数据类型 变量名 : 源){
		
	}

注意:源可以是数组或者集合(Iterable的实例)

  1. 使用迭代器进行遍历
    Iterator 就是一个迭代器(也是一个接口)
    其中的方法如下:
	//boolean hasNext() 判断是否有下一个元素,如果返回true表示有下一个;
	//Object next() 调用一次获得一个元素(每调用一次指针会向后移动一个);
	//void remove() 会从迭代器指向的结合容器中删除一个元素
		ArrayList bag = new ArrayList();
			bag.add("电脑");
			bag.add(200);
			bag.add("鼠标");
			bag.add("小人书");
			bag.add("教材");
			bag.add("牛奶");
			
			//使用迭代器遍历集合ArrayList   bag
			// 获得一个迭代器
			Iterator it = bag.iterator();
			while(it.hasNext()){
				System.out.println(it.next());
			}	
  1. 双向迭代器
    Iterator 单向的迭代器接口,从左到右依次获得数据,判断是否有下一个;获得下一个
    |-- ListIterator 双向的迭代器接口,它的主要方法如下:
	//Iterator中有的它也有;
	//boolean hasPrevious() 判断是否有上一个;
	//Object  previous() 获得上一个元素;
	ArrayList bag = new ArrayList();
			bag.add("电脑");
			bag.add(200);
			bag.add("鼠标");
			bag.add("小人书");
			bag.add("教材");
			bag.add("牛奶");
			// 获得双向的迭代器
			ListIterator iterator = bag.listIterator();
			while(iterator.hasNext()){
				System.out.println(iterator.next());
			}
	
			System.out.println("------------------------------------------");
			
			while(iterator.hasPrevious()){
				System.out.println(iterator.previous());
			}

LinkedList

语法特点
内部是基于双向链表结构实现的。添加和删除比较快,查询相对ArrayList比较慢

  1. 内部相对于ArrayList而言多了一些操作头和尾的方法
  2. 可以充当队列,堆栈
  3. 不是线程安全的(同步的)

总结:LinkedList底层是基于双向链表容器类,添加和删除比较快。查找和修改较慢。

基本使用

参照ArrayList  把ArrayList 改成 LinkedList

c. 遍历方式

参照ArrayList  把ArrayList 改成 LinkedList

Set

HashSet

语法特点:不重复,无序(不保证和添加顺序一致)
不能够添加重复元素

是否重复判断规则

  1. 判断重复的方式
    a. 通过添加进去的元素的hashCode+eqauls 两者进行比较
    b. 如果两个对象的hashCode相等 并且 两个对象调用equals结果是true 才认为两个元素重复

  2. 验证上面的规则
    a. 打印上面示例中的元素的hashCode和equals的结果
    b. 2 尝试自定义类,覆写hashCode 和 equals 这两个方法中的代码随便写
    在这里插入图片描述

  3. 实际开发情况分析(重点)
    a. 从上面的示例来看,结果两个都添加进去了,原因:hashCode不等,equals为false
    b. 从业务上来看(需要向源码时代学生管理系统中添加两个学生信息),觉得这两天数据是同一个人
    c. 应该怎么做: 在Student中覆写hashCode 和equals方法
    在这里插入图片描述
    d. 怎么覆写?
    覆写的时候应该参考实际业务中的比较规则,例如姓名,年龄等(还得看Student类中有哪些字段,并且这些字段是业务人员判断的标准)
    自动生成:
    在这里插入图片描述

TreeSet
语法特点
无序:不保证(不记录)我们的添加顺序;但是可以保证添加里面元素是有序的。

public static void main(String[] args) {
		 Set<String> set = new HashSet<String>();
	        set.add("catepillar");
	        set.add("momor");
	        set.add("bush");
	        set.add("cateprillar");
         System.out.println(set);
}

不重复:不能够添加重复元素(多个心眼)如何判断重复的呢?

简单体验

  1. 体验1
    在这里插入图片描述
    结果: 虽然打印结果的顺序和添加顺序可能不一致,但是感觉结果是有某种规则排序的
    说明String类也实现了Comparable接口,String对象可以调用compareTo方法

  2. 体验2
    在这里插入图片描述
    结果:居然不能够放不同的类型,但是编译没有错

  3. 体验3: 添加自定义的类的对象 Student对象
    在这里插入图片描述
    结果:
    疑问1:上面的代码添加的都是同种类型的数据,为什么还报错;
    疑问2:为什么提示要把Student转成Comparable
    正常情况 ----》 TreeSet 或者 Comparable的文档

TreeSet的结构(存储原理)分析
在这里插入图片描述

自然排序与定制排序(比较器)

  • 自然排序 Comparable
    从TreeSet的API文档中点击 “自然排序” —》 Comparable接口中
    文档中的描述:
    此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法

    理解:
    如果一个类实现了Comparable接口,可以认为这个类的对象具有自然排序的能力(本质就是这个对象可以调用比较的方法compareTo),这种比较和排序的规则就是自然排序
    在这里插入图片描述
    在这里插入图片描述

  • 定制排序(比较器)Comparator
    根据上面的分析,如果我们的对象没有实现Comparable接口,感觉就无法添加到TreeSet中去;(这些对象就没有自然排序的能力);
    上面的示例设计有点问题:Student类中覆写的compareTo方法按照年龄从小到大排列的,万一有的人也是用我们的Student,希望年龄从大到小进行排列,怎么办?
    不管Student里面使用何种规则都不能满足所有的人
    解决办法: 可以给TreeSet单独的提供一个比较器(理解为比较的一个工具)
    Comparator 是一个比较器的接口(标准),必须得有进行比较的方法 :compare(Object o1,Object o2);
    自定义一个类实现Comparator接口,其中写比较规则 —》 比较器的模板
    我们现在需要的是一个具体的比较器对象

示例:
在这里插入图片描述
在这里插入图片描述

判断重复的标准
1、如果采用的是自然排序调用对象的compareTo方法,如果返回0 表示相等;
2、如果使用的定制排序(比较器),调用比较器的方法compare 返回0 表示相等;

Map

将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

Map方法和存储结构
Map方法介绍

put(K key, V value)  在此映射中关联指定值与指定键。
	如果key不存在,直接添加进去
	如果key相同,value值使用最新的值替换key对应的老值.
	put方法会返回 对应key对应的老值 

boolean containsKey(Object key)  如果此映射包含对于指定键的映射关系,则返回 true。
boolean  containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。
get(Object key)  返回指定键所映射的值。(通过键得到值)

Map特点

Map特点:
一个Map对象中不能有重复的键。
Map怎么判断重复?

  1. 通过put方法,put一次的时候,就是放两个参数,一个key,一个value,put方法相等于添加方法,在put的时候,判断当前放的这对(key-value)是否和里面已经存在的对(key-value) 是否已经重复, 只是在put的时候,放了两个参数,一个key和value,它判断重复,使用哪个参数?

  2. 使用key作为判断重复的标准.只拿key 和已经存在的一对一对key进行比较;就少拿了一个value而已;这个原理和HashSet,TreeSet一样。设计Map的时候,并没有说具体按照什么进行判断重复,而是通过实现类进行判断;

Map存储方式
Map的存储原理:

利用封装的,如果要封装,首先有个类型,这个类型是Entry,
Entry类型作用:Entry用来封装用户添加的一对数据.Entry类型有两个字段,添加的时候,使用Entry把两个值封装成一个对象,然后放到Map容器里面。对于Map而言,看到的只有Entry对象。
由于Entry的存在,只是对于Map来讲才有意义. 因此它使用封装,把Entry类型设计到Map里面。相当于内部类。

Map 里面的方法

entrySet()  返回Set,(返回当前Map中所有的entry对象,使用Set存储起来。)
keySet()    返回Map当中所有的key,存储到一个Set集合当中。
values()    返回所有的values,存储到一个Collection。
get(Object key)  返回Collection,通过key查找对应的值。
这里get方法为什么返回Collection?
因为values 有重复,如果返回Set,就不能含有重复的元素.

values方法
示例:利用Map来存储各位的姓名和年龄,比如
“小鹏鹏” – 18 ,最后计算本班级的平均年龄。
实现代码:
在这里插入图片描述
Map两种遍历方式
遍历Map 之 keyset方式
先得到所有key, 通过keySet方法取到;
然后遍历keySet,依次通过key来查找value。
通过Object get(Object key)方法;
在这里插入图片描述

遍历Map 之 Entry对象方式
先得到所有的Entry对象,Entry对象就包装了key,values;
遍历Entry对象的集合,然后依次从Entry对象中调用方法:getKey(),getValue()
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值