1.List集合: 1.1概述:
有序的colletion(也称为序列).此接口的用户可以对列表中的每个元素的插入位置进行精确的控制,用户可以根据元素的整数索引(在列表中的位置)来访问元素,并搜索列表中的元素.
1.2 特点:- 元素都有下标
- 数据是有序的
- 允许存放重复的元素
- 存在java.util包中
- 内部是用数组结构存放数据,封装数组的操作,每个对象都有下标
- 内部数组默认的初始容量是10,如果不够会以1.5倍的容量增长
- 查询快,增删数据效率会低
链表,两端效率高,底层就是链表实现的
4.ArrayList:
ArrayList相当于在没指定initialCapacity时就是会使用延迟分配对象数组空间,当第一次插入元素时才分配10(默认)个对象空间。假如有20个数据需要添加,那么会分别在第一次的时候,将ArrayList的容量变为10;之后扩容会按照1.5倍增长。也就是当添加第11个数据的时候,Arraylist继续扩容变为10*1.5=15;当添加第16个数据时,继续扩容变为15 * 1.5 =22个
ArrayList没有对外暴露其容量个数,查看源码我们可以知道,实际其值存放在elementData对象数组中,那我们只需拿到这个数组的长度,观察其值变化了几次就知道其扩容了多少次。怎么获取呢?只能用反射技术了。
4.Map 4.1特点
- Map可以根据键来提取对应的值
- Map的键不允许重复,如果重复,对应的值会被覆盖
- Map存放的都是无序的数据
- Map的初始容量是16,默认的加载因子是0.75
HashMap的结构是数组+链表 或者 数组+红黑树 的形式
HashMap底层的Entry[ ]数组,初始容量为16,加载因子是0.75f,扩容按约为2倍扩容
当存放数据时,会根据hash(key)%n算法来计算数据的存放位置,n就是数组的长度,其实也就是集合的容量
当计算到的位置之前没有存过数据的时候,会直接存放数据
当计算的位置,有数据时,会发生hash冲突/hash碰撞
解决的办法就是采用链表的结构,在数组中指定位置处以后元素之后插入新的元素
也就是说数组中的元素都是最早加入的节点
如果链表的长度>8时,链表会转为红黑树,当链表的长度<6时,会重新恢复成链表
package cn.tedu.list;
import java.util.*;
public class MapDemo {
public static void main(String[] args) {
//1.创建Map对象
Map map = new HashMap<>();//注意导包:java.util
//2.向map集合存入数据,注意方法是put(),并且需要存入一对的值
map.put(9527,"白骨精");
map.put(9528,"黑熊精");
map.put(9529,"鲤鱼精");
map.put(9530,"黄毛怪");
map.put(9531,"黑熊精");
map.put(9527,"女儿国国王");
System.out.println(map);//查看map集合中的数据是否存入成功
//3.进行方法测试
//map.clear();//清空集合
System.out.println(map.hashCode());//获取集合的哈希码
System.out.println(map.equals("黄毛怪"));//判断“黄毛怪”是否与集合对象相等
System.out.println(map.isEmpty());//判断集合是否为空
System.out.println(map.size());//获取集合中元素的个数
//判断当前map集合中是否包含指定的Key键
System.out.println(map.containsKey(9527));//true
//判断当前map集合中是否包含指定的Value
System.out.println(map.containsValue("白骨精"));//false,因为已被覆盖
//根据key值获取到对应的value值
System.out.println(map.get(9530));
//根据此key值对应的键值对,K与V都删了
System.out.println(map.remove(9529));
System.out.println(map.containsKey(9529));
System.out.println(map.containsValue("鲤鱼精"));
//将map集合中的所有value取出,放入Collection集合中
//Collection中Type的类型,取决于map中value的类型
Collection values = map.values();
System.out.println(values);//[女儿国国王, 黑熊精, 黄毛怪, 黑熊精]
//4.map集合的迭代方式一
//4.1将map集合中的key值取出存入set集合中,集合的泛型就是key的类型Integer
Set keySet = map.keySet();
//4.2想要遍历集合就需要获取集合的迭代器
Iterator it = keySet.iterator();
//4.3循环迭代集合中的所有元素
while(it.hasNext()){//判断是否有下一个元素可以迭代
Integer key = it.next();//拿到本轮循环中获取到的map的key
String value = map.get(key);
System.out.println("{"+key+","+value+"}");
}
Set> entrySet = map.entrySet();
//获取迭代器
Iterator> it2 = entrySet.iterator();
while(it2.hasNext()){//判断是否有下一个元素可迭代
//本轮遍历到的一个Entry对象
Map.Entry entry = it2.next();
Integer key = entry.getKey();//获取Entry中的key
String value = entry.getValue();//获取Entry中的value
System.out.println("{"+key+","+value+"}");
}
}
}
5.set
概述
- Set是一个不包含重复数据的Collection
- Set集合中的数据是无序的(因为Set集合没有下标)
- Set集合中的元素不可以重复 – 常用来给数据去重
- 数据无序且数据不允许重复
- HashSet : 底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。当然K仍然不许重复。
- TreeSet : 底层是TreeMap,也是红黑树的形式,便于查找数据
底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K存入内部的HashMap中,其中K不允许重复,允许使用null.
为什么要有集合迭代器:集合必须是有限的,而迭代器则不必。
比如说,让你迭代所有的正整数,你可以1 2 3 4 5 ... 一直迭代下去。
但是你不能把所有的整数装入一个集合。
即便遍历的对象不是无限多的,比如说,我让你找出csdn问答中最新的n条提问来。
你如果用集合,那么首先要把csdn所有的问题都放入一个集合,虽然这是有限的,但是也是不经济的。
而用迭代器,我只要从最新的页面开始,一条一条给你,直到给你n条,就结束。
迭代器的作用在于,将遍历的逻辑(迭代器)和对每一个迭代对象(迭代器调用代码)分开,使得遍历可以被重用。如果没有迭代器,要么代码调用者必须自己一遍一遍写遍历的代码,有时候这个过程会很麻烦,比如遍历文件系统,或者取一个数列的前n项。要么让遍历的结果装入一个集合并返回,但是这么做的问题是,我们并不知道需要返回多少项,比如求比1000小的素数的和,你没法将需要返回多少项作为参数传进去,如果你把遍历后判断这个素数是不是小于1000的代码写在遍历中,又使得调用和被调用代码混合在一起了。



