LIST
ArrayList
1 语法特点
1、内部基于数组实现的一个集合类。查询比较快,添加和删除相对比较慢
2、猜ArrayList中会有哪些功能(方法): 添加、删除、查询、插入、修改。。。
3、不是同步的(存在线程安全问题),如何解决:敬请期待... 用Vector
2 基本使用
参考api一个一个写
1 三个构造函数
2 增删改查
3 数组和List相互转化
3 遍历方式
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));
}
2、增强for循环(foreach)
语法:
for(源中的数据类型 变量名 : 源){
}
注意:源可以是数组或者集合(Iterable的实例)
3、使用迭代器进行遍历
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
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());
}
一个一个next
多次迭代
遍迭代遍删除-两个错误演示
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
结果:只遍历了一次,为什么?
原因:上面两个while使用的是同一个迭代器,第一个while循环完毕就把指针移动到末尾了,所以第二个while不会执行了
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
4、双向迭代器
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
语法特点
1、 内部是基于双向链表结构实现的。添加和删除比较快,查询相对ArrayList比较慢
2、 内部相对于ArrayList而言多了一些操作头和尾的方法
3、 可以充当队列,堆栈
4、 不是线程安全的(同步的)
总结:LinkedList底层是基于双向链表容器类,添加和删除比较快。查找和修改较慢。
SET
HashSet
语法特点:不重复,无序(不保证和添加顺序一致)
1、不能够添加重复元素
2、初体验
可以添加案例:测试不重复和有序。
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
判断重复的方式
① 通过添加进去的元素的hashCode+eqauls 两者进行比较
② 如果两个对象的hashCode相等 并且 两个对象调用equals结果是true 才认为两个元素重复
③ 示意图
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
验证上面的规则
1 打印上面示例中的元素的hashCode和equals的结果
2 尝试自定义类,覆写hashCode 和 equals 这两个方法中的代码随便写
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
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);
}
自然排序与定制排序(比较器)
自然排序 Comparable
从TreeSet的API文档中点击 “自然排序” ---》 Comparable接口中
文档中的描述:
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法
理解:
如果一个类实现了Comparable接口,可以认为这个类的对象具有自然排序的能力(本质就是这个对象可以调用比较的方法compareTo),这种比较和排序的规则就是自然排序
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
定制排序(比较器)Comparator
1、根据上面的分析,如果我们的对象没有实现Comparable接口,感觉就无法添加到TreeSet中去;(这些对象就没有自然排序的能力);
2、上面的示例设计有点问题:Student类中覆写的compareTo方法按照年龄从小到大排列的,万一有的人也是用我们的Student,希望年龄从大到小进行排列,怎么办?
不管Student里面使用何种规则都不能满足所有的人
3、解决办法: 可以给TreeSet单独的提供一个比较器(理解为比较的一个工具)
4、Comparator 是一个比较器的接口(标准),必须得有进行比较的方法 :compare(Object o1,Object o2);
自定义一个类实现Comparator接口,其中写比较规则 ---》 比较器的模板
我们现在需要的是一个具体的比较器对象
示例:
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
判断重复的标准
1、如果采用的是自然排序调用对象的compareTo方法,如果返回0 表示相等;
2、如果使用的定制排序(比较器),调用比较器的方法compare 返回0 表示相等;
MAP
概念:
1) Map :将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
2) 现在需要创建一个Map对象,装里面的数据,但是发现Map是接口,应该怎么创建对象?
3) 使用实现类 HashMap 创建对象;
HashMap简单使用:
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
从定义上看 Map是不能有重复的键,练习使用一下:
put(K key, V value) 在此映射中关联指定值与指定键。
put方法特点:
1. 如果key不存在,直接添加进去
2. 如果key相同,value值使用最新的值替换key对应的老值.
put方法会返回 对应key对应的老值
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
1. Map方法和存储结构
1 Map方法介绍
现在我们对于Map的初步使用,是能够放一对一对的键值对;刚才使用到put方法,看一下
其他的方法:
boolean containsKey(Object key) 如果此映射包含对于指定键的映射关系,则返回 true。
boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。
get(Object key) 返回指定键所映射的值。(通过键得到值)
只有通过键拿值,但是为什么没有通过值得到键呢?
因为键是唯一的,通过键可以找到唯一值,而值不是唯一,通过值,可能找到多个键,
如果需要这样的方法,应该返回数组或者集合。
get方法练习使用:
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
putAll(Map<? extends K,? extends V> m) 将指定映射的所有映射关系复制到此映射中,这些映射关系将替换此映射目前针对指定映射中所有键的所有映射关系。(相当于Collection下面的addAll,把另外一个Map放到当前Map的容器里面)
remove(Object key) 从此映射中移除指定键的映射关系(通过key ,找到value,然后把一对键和值都删掉)。
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
2 Map特点
现在只是使用了一下HashMap,介绍了HashMap的方法,并没有说明HashMap的特点,它有什么特点呢?
Map特点:
一个Map对象中不能有重复的键。
Map怎么判断重复?
通过put方法,put一次的时候,就是放两个参数,一个key,一个value,put方法相等于添加方法,在put的时候,判断当前放的这对(key-value)是否和里面已经存在的对(key-value) 是否已经重复, 只是在put的时候,放了两个参数,一个key和value,它判断重复,使用哪个参数?
使用key作为判断重复的标准.只拿key 和已经存在的一对一对key进行比较;就少拿了一个value而已;这个原理和HashSet,TreeSet一样。设计Map的时候,并没有说具体按照什么进行判断重复,而是通过实现类进行判断;
示例:
看下面代码是否能编译通过?
Map map = new HashMap();
map.put(new A(),123);
TreeMap m = new TreeMap();
m.put(new A(),45);
报错信息:
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
那把字符串作为key放进去编译能通过不?
m.put(“sdfa”,45);
Map接口
|---HashMap 判断重复的标准和HashSet一致,通过键的hashcode和equals;
|---TreeMap 判断重复的标准和TreeSet一致,1通过自然排序(Comparable接口),2定制排序(Compartor比较器)
这就是HashMap,TreeMap的特点;
3 Map存储方式
现在分析一下:Map在存储的时候的使用什么存储方式?
在Map使用的时候,添加一对值使用put方法,那在Map里面是怎么存储的?
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
它和我们在设计链表结构linkedList非常相像。基于链表结构封装成容器类,那我们是怎样存储的?
把值封装成一个对象,并且里面有其他字段。
Map的存储原理也是类似:利用封装的,如果要封装,首先有个类型,这个类型是Entry,
Entry类型作用:Entry用来封装用户添加的一对数据.Entry类型有两个字段,添加的时候,使用Entry把两个值封装成一个对象,然后放到Map容器里面。对于Map而言,看到的只有Entry对象。
由于Entry的存在,只是对于Map来讲才有意义. 因此它使用封装,把Entry类型设计到Map里面。相当于内部类。
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
Map 里面的方法:
entrySet() 返回Set,(返回当前Map中所有的entry对象,使用Set存储起来。)
keySet() 返回Map当中所有的key,存储到一个Set集合当中。
values() 返回所有的values,存储到一个Collection。
get(Object key) 返回Collection,通过key查找对应的值。
这里get方法为什么返回Collection?
因为values 有重复,如果返回Set,就不能含有重复的元素. 3.avi]
4 values方法
示例:利用Map来存储各位的姓名和年龄,比如
“小鹏鹏” -- 18 ,最后计算本班级的平均年龄。
实现代码:
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
[4.avi]
2. Map两种遍历方式
使用集合存数据经常会使用到遍历问题. 那现在想把Map里面的key,values 一个一个打印出来,怎么实现?
遍历Map,已学过的遍历(数组,Collection)的方式:
① 普通for
② 增强for
③ 迭代器
使用普通for循环能不能遍历Map元素?
不能,没有索引;
使用增强for行不行?
不能,没有实现Iterable接口;
使用迭代器(Iterator)行不行?
Map里面并没有获得迭代器的方法;所有不能使用迭代器;
三种方式都不行. 怎么办?
对于Map的遍历,有其他的方式,
要从Map取得一个元素,通过key 找到value,那要找所有value,就应该先取得所有key。
方式一:----------------------------------------------------->
①先得到所有key,怎么得到?
通过keySet方法取到;
②然后遍历keySet,依次通过key来查找value。
通过Object get(Object key)方法;
方式二:----------------------------------------------------->
①先得到所有的Entry对象,Entry对象就包装了key,values,
②遍历Entry对象的集合,然后依次从Entry对象中调用方法:
getKey(),getValue()
方法里面为什么没有参数?
因为这个方法在Entry对象里面,在一个Entry对象里面只有一个key,一个value,相当于Student,有个name,age字段,获取name,age不需要添加参数;
1 遍历Map 之 keyset方式
KeySet方式:
①先得到所有key, 通过keySet方法取到;
②然后遍历keySet,依次通过key来查找value。
通过Object get(Object key)方法;
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
2 遍历Map 之 Entry对象方式
Entry对象方式: [5.avi]
①先得到所有的Entry对象,Entry对象就包装了key,values;
②遍历Entry对象的集合,然后依次从Entry对象中调用方法:getKey(),getValue()
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
[5.avi]
3. Map 应用
Map使用示例:
有如下字符串,String str = “ aaaabbbyyyccc’;
①统计出str中每一个字符的个数
比如 a - 4
b - 3
②找出并打印,次数最多的字符和次数
分析①:
使用Map进行存储 ,
字符 - key
次数 - value
遍历字符串(依次取得每一个字符)。一边取一边放在Map中,在存放前应该先判
断当前的Map容器中是否存在当前得到的这个字符。
如果没有,那么说明是第一次 应put(ele,1);
如果有,以当前的字符作为key从Map中取出对应的value,在+1 ----》新的value值 put(ele,新value);
如下代码:
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
②找出并打印,次数最多的字符和次数{b = 3,c=3,a=4,y=3}
相当于找出一个Map中value值最大的那一组.
找到最大的value值;根据先得到的所有value,然后自己遍历比较
找最大值方式一:
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
找最大值方式二:
调用Collection中的toArray方法,把Collection 转换成数组,然后调用Arrays中的工具方法sort求出;(val.toArray()方法和Arrays.sort(数组对象)方法)
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
找最大值方式三:
直接调用Collection里面的max方法
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
最大值得到之后,根据最大值找到key,通过value找到key,只有遍历Map一个一个进行比较;
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
[6.avi]
4. Collections工具类
通过刚才的示例,使用到了Collections, 那Collections里面都有什么内容?
addAll(Collection<? super T> c, T... elements)将所有指定元素添加到指定 collection 中。
![fef966490015c0764e9f25abf67e2466.png](https://img-blog.csdnimg.cn/img_convert/fef966490015c0764e9f25abf67e2466.png)
copy(List<? super T> dest, List<? extends T> src) 将所有元素从一个列表复制到另一个列表
shuffle(List<?> list) 使用默认随机源对指定列表进行置换
fill(List<? super T> list, T obj) 使用指定元素替换指定列表中的所有元素。
max(Collection<? extends T> coll) 根据元素的自然顺序,返回给定 collection 的最大元素。
max(Collection<? extends T> coll, Comparator<? super T> comp) 根据指定比较器产生的顺序,返回给定 collection 的最大元素。
min(Collection<? extends T> coll) 根据元素的自然顺序 返回给定 collection 的最小元素。
min(Collection<? extends T> coll, Comparator<? super T> comp) 根据指定比较器产生的顺序,返回给定 collection 的最小元素。
sort(List<T> list) 根据元素的自然顺序 对指定列表按升序进行排序。
sort(List<T> list, Comparator<? super T> c)根据指定比较器产生的顺序对指定列表进行排序。
synchronizedList(List<T> list) 返回指定列表支持的同步(线程安全的)列表。