1.1目录
1. 为什么使用集合? 2. 集合架构有哪些? 3. List集合 4. ArrayList集合 5. LinkedList集合。
1.2 为什么使用集合?
1. 我们原来讲过数组. 当我们需要保持一组一样(类型相同)的元素的时候,我们应该使用一个容器来保存,数组就是这样一个容器。 思考: 数组有缺陷?--定容【一定数组定义好,他们得长度就无法改 变.】如果需要改变数组得长度,变得很复杂。 2.那么,数组的缺点是什么呢? 数组一旦定义,长度将不能再变化。 3.我们在开发中,需要保存一些变长的数据集合,所以我们需要一些能够动态增长长度的容器来保存我们的数据。 4.我们需要对数据的保存的逻辑有了各种各样的数据结构。我们将数据结构在Java中实现,于是就有了我们的集合框架。
1.3 集合的架构![](https://i-blog.csdnimg.cn/blog_migrate/558898124af3e19257123cd5968ba6cc.png)
1.4 List集合![](https://i-blog.csdnimg.cn/blog_migrate/f5a23cadde4bdb0c8d1d0638602968da.png)
1.4.0 创建集合对象
List list = new ArrayList(); //创建一个集合对象 如果没有指定集合容器的长度默认为10
List list1 = new ArrayList(15);
1.4.1 添加的操作1.4.2 修改的操作
//修改操作
list.set(1,"张三");
System.out.println(list);
1.4.3 查询操作1.4.4 删除的操作
//删除操作
list.remove(2);//移除下标为2的元素
System.out.println(list);
list.clear();//清空集合中的元素
System.out.println(list);
1.5.LinkedList
1.5.1 添加操作
//添加操作
linkedList.add("java01");//添加操作
linkedList.addFirst("java02");//添加到头部
linkedList.addLast("java03");//添加到尾部
1.5.2 查询操作
//查询操作
System.out.println(linkedList.size());//获取数组长度
System.out.println(linkedList.isEmpty());//获取数组是否为空
System.out.println(linkedList.contains("java05"));//判断元素是否在数组内
System.out.println(linkedList.get(1));//获取下标为一的元素
System.out.println(linkedList.getFirst());//获取头部元素
System.out.println(linkedList.getLast());//获取尾部元素
1.5.3 删除操作
//删除操作
linkedList.remove(1);//删除下标为一的数据
linkedList.removeFirst();//删除头部
linkedList.removeLast();//删除尾部
System.out.println(linkedList);
1.5.4 修改操作
//修改操作
linkedList.set(1,"李四");
System.out.println(linkedList);
1.5.5LinkedList的get()查询操作的源代码
1、==================== get(1)-----获取元素========================
public E get(int index) {
checkElementIndex(index); //检查index下标是否正确。
return node(index).item; //李四Node对象
}
========================node(index)=============================
Node<E> node(int index) {
//>> 位运算二进制运算 ----- size >> 1 一半的意思size/2
if (index < (size >> 1)) { //前半部分
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else { //后半部分
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
1.6 Set集合
1.7 HashSet集合
1.7.0 创建HashSet对象
public class Test02 {
public static void main(String[] args) {
HashSet hashSet= new HashSet();
HashSet hashSet1 = new HashSet(16);//初始容器的大小
//loadFactor:--->0.7f 表示负载因子 当空间使用70%时 要求扩容
HashSet hashSet2 = new HashSet(16,0.7f);
}
}
1.7.1 添加元素
//添加操作
hashSet.add("java01");
hashSet.add("java02");
hashSet.add("java04");
hashSet.add("java03");
hashSet.add("java02");
HashSet set2=new HashSet();
set2.add("易烊千玺");
set2.add("王俊凯");
set2.add("王源");
hashSet.addAll(set2); //把set2中的每个元素添加到hashset中
System.out.println(hashSet); //元素不能重复 而且无序
1.7.2 删除元素
//删除
hashSet.remove("王源");
// hashSet.clear();//清空容器集合
System.out.println(hashSet);
1.7.3 修改元素
//修改操作
boolean empty = hashSet.isEmpty(); //判断是否为空
System.out.println(empty);
boolean b = hashSet.contains("易烊千玺");//判断元素是否在容器中
System.out.println(b);
1.7.4 hashSet的遍历
(1)通过foreach遍历
//遍历--- foreach
for(Object o: hashSet){
System.out.println(o);
}
(2)通过迭代器来遍历
//迭代器遍历
Iterator iterator = hashSet.iterator();//获取迭代器对象 有序:有下标
while (iterator.hasNext()){//判断是否指定能够移动
Object next = iterator.next();//指定移动并获取当前的元素
System.out.println(next);
}
1.8 TreeSet集合
TreeSet中的方法和HashSet中的方法一模一样 只是他们的实现不一样。
TreeSet 基于TreeMap 实现。TreeSet可以实现有序集合,但是有序性需要通过比较器实现。
例子: 存储String类型
存储一个对象类型:
1.8.0 在创建TreeSet时 为其指定排序得规则
新建一个选择器类型的对象,在创建TreeSet对象时传入参数
public class MyComparator implements Comparator {
@Override
public int compare(Object o1, Object o2) {
Student student1 = (Student) o1;
Student student2 = (Student) o2;
if (student1.getAge() > student2.getAge()){
return 1;
}
if (student1.getAge() < student2.getAge()){
return -1;
}
return 0;
}
}
public class TestTreeSet {
public static void main(String[] args) {
TreeSet treeSet2 = new TreeSet(new MyComparator());
treeSet2.add(new Student("易烊千玺",22));
treeSet2.add(new Student("王俊凯",23));
treeSet2.add(new Student("王源",22));
System.out.println(treeSet2);
// [Student{name='易烊千玺', age=22}, Student{name='王俊凯', age=23}, Student{name='王源', age=22}]
}
}
1.9 Map 属于键值对模式
Map中得每个元素属于键值对模式。 如果往map中添加元素时 需要添加key 和 value. 它也属于一个接口,该接口常见得实现类有: HashMap
1.9.0 如何创建Map对象
public class TestHashMap {
public static void main(String[] args) {
//默认容量为16,负载因子为0.75
Map map = new HashMap();
//初始化大小
HashMap map1 = new HashMap(16);
//初始化大小 负载因子
HashMap map2 = new HashMap(16,0.78f);
}
}
1.9.1 添加操作
public class TestHashMap {
public static void main(String[] args) {
//默认容量为16,负载因子为0.75
Map map = new HashMap();
HashMap map1 = new HashMap(16);
HashMap map2 = new HashMap(16,0.78f);
//添加操作 key: name value: 张三
map.put("name","张三");//注意: 要求map得key必须唯一。
map.put("age",22);
map.put("name","李四");//因为key不能重复,所以后者会把前者覆盖
System.out.println(map);
map1.put("k1","v1");
map1.put("k2","v2");
//putAll:把m1中得每个元素 添加到map中
map.putAll(map1);
System.out.println(map);
//putIfAbsent:如果指定得key存在,则不放入map中,如果不存在则放入map中
map.putIfAbsent("age",24);
System.out.println(map);
}
}
1.9.2 删除操作
//删除操作
map.remove("age2");//根据指定得key移除元素
System.out.println(map);
map.clear(); //清空map容器
System.out.println(map);
1.9.3 修改操作
//修改操作
map.replace("name","王五");//替换元素
System.out.println(map);
1.9.4 查询操作
get(key):获取key的value值
containsKey(key):返回值为布尔类型,是否包含key为指定内容的元素
keySet():返回值为Set对象,获取map中的所有key值,并存储为Set对象,使用for each 遍历keySet,输出key和value
Object v = map.get("name"); //根据指定的key获取对应得value值
System.out.println(value);
Set keys = map.keySet();//返回该map中所有得key
System.out.println(keys);
//遍历map.
for (Object o : keys){
System.out.println(o+"----->"+map.get(o));
}
}
1.10HashMap集合
JDK1.7使用的数据结构:数组+链表,而且链表插入模式为头部插入(容易造成死循环)。
JDK1.8使用的数据结构:数组+链表+红黑树,而且链表的插入模式为尾部插入。
1.10.0HashMap的过程
1.10.1jdk1.7和jdk1.8中hashMap的区别
jdk1.7中:数组+单向链表 而链表的插入为头部插入(容易造成死循环)
jdk1.8中:数组+单向链表+红黑树 链表的插入方式为尾部插入,当hash碰撞的个数超过8个时,单向链表转换为红黑二叉树。
1.10.2 JDK1.8 HashMap原理
JDK1.8 HashMap原理
Hashmap得原理,存储元素使用得put(key,value),根据key得hash计算出相应得哈希值,根据相应得算法求出该元素在数组中得位置, 如果求出得哈希值相同,则称为哈希冲突,会根据equals来判断元素是否一致,如果equals不同,则存入单向链表上, 如果哈希碰撞得个数超过8个,则把链表转换为红黑二叉树。