Java集合(Collection+Map)
- 为什么要使用集合?
- 泛型 <>
- 集合框架
- 单列集合Collection
- Collection遍历方式
- List:有序、可重复、有索引
- ArrayList
- LinkedList
- Vector(已经淘汰,不会再用)
 
- Set:无序、不重复、无索引
- HashSet
- LinkedHashSet
 
- TreeSet
 
 
- 双列集合Map
- HashMap
- LinkedHashMap
 
- HashTable(后续补充)
- Properties
 
- TreeMap
 
- Collections 集合工具类
 
来自黑马,把视频截图保存,主要为了自己方便查找。
为什么要使用集合?
当有很多数据需要存储时,会想到用数组,而数组需要在定义时指定长度,而我们希望有一个可变长度的容器——集合。
 集合可以自动扩容,提高了数据存储的灵活性,Java 集合不仅可以用来存储不同类型不同数量的对象,还可以保存具有映射关系的数据。
 
泛型 <>

集合框架

红色表示接口,蓝色表示实现类:
 
 
 键和值之间一一对应。键值对也成为键值对对象,或者是Entry对象。
 
 

单列集合Collection


 
 
 
 在Java里面,字符串已经重写好了equals方法。

Collection遍历方式
以前的普通的for循环的遍历方式适用于有索引的list系列,而没有索引的set系列不能用。
1. 迭代器遍历
 
 

2. 增强for遍历
 
 
 3. lambda表达式遍历
 
 一行搞定:
 
List:有序、可重复、有索引

- 添加元素:添加完之后,原来索引上的元素会依次后移。
- 删除元素:下面第一个会删除1索引,第二个装箱了,会删除“1”
  
独有的遍历方式: 继承了Collection的遍历方式。
- 迭代器
- 增强for
- Lambda表达式
- 普通for循环(因为List集合存在索引)
  
- 列表迭代器遍历
  
 总结:
  
ArrayList

输出是 []

import java.util.*;
public class Main {
    public static void main(String[] args) {
        //1.创建一个集合
        ArrayList<String> list = new ArrayList<>();
        System.out.println(list);  //[]
        //2.添加元素: 对于add方法,在ArrayList里面,不管添加什么,都会返回true
//        boolean result = list.add("aaa");
//        System.out.println(result);  //true
//        System.out.println(list);  //[aaa]
        // 所以一般直接添加元素就行,不用管返回值
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        System.out.println(list);  //[aaa, bbb, ccc]
        //3.删除元素
        list.remove("aaa");
        System.out.println(list);  //[bbb, ccc]
        String str = list.remove(0);  //这里也可以不接收返回值,直接list.remove(0)
        System.out.println(str);  //bbb
        System.out.println(list);  //[ccc]
        //4.修改元素
        String str1 = list.set(0, "ddd");
        System.out.println(str1);  //ccc,返回被覆盖的元素
        System.out.println(list);  //[ddd],结果就是覆盖以后的
        //5.查询元素
        String str2 = list.get(0);
        System.out.println(str2);  //ddd,获取单个元素
        //遍历
        list.add("eee");
        list.add("fff");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));  //依次输出ddd eee fff
        }
        System.out.println(list);  //[ddd, eee, fff],直接打印就是集合
    }
}
LinkedList

 我们在项目中一般是不会使用到 LinkedList 的,需要用到 LinkedList 的场景几乎都可以使用 ArrayList 来代替,并且,性能通常会更好!就连 LinkedList 的作者约书亚 · 布洛克(Josh Bloch)自己都说从来不会使用 LinkedList 。
另外,不要下意识地认为 LinkedList 作为链表就最适合元素增删的场景。我在上面也说了,LinkedList 仅仅在头尾插入或者删除元素的时候时间复杂度近似 O(1),其他情况增删元素的时间复杂度都是 O(n) ,因为需要从头或尾开始寻找!
Vector(已经淘汰,不会再用)
Set:无序、不重复、无索引

set遍历:
 
首先添加元素,如果是第一次添加,返回True,第二次就不行了,返回False:
 
遍历:
 
HashSet

 
 
 
 
 

 加载因子表示的是扩容时机,当数组里面的元素到了16*0.75=12个的时候,数组长度就加倍,变成了32。而当链表长度大于8而且数组长度大于等于64,就会自动编程红黑树:
 
了解了底层原理,就可以回答HashSet的问题:
 
 如图所示,读取的顺序是图中的123456,但是存的顺序就不一定了。
问题2:HashSet为什么没有索引?
 图中1索引对应的位置有好几个元素,不好区分,所以干脆无索引。
问题3:HashSet是利用什么机制保证数据去重的?
 用HashCode方法和equals方法,所以如果集合中存储的是自定义对象(如Student),一定要根据对象的属性重写这两个方法,要不然就会比较地址值!
这里为什么会强调自定义对象要重写:如果存储的是基本数据类型的包装类,已经正确地重写了hashCode()和equals()方法。对于 Java 标准库中的许多类(如String),也已经合理地重写了hashCode()和equals()方法。
LinkedHashSet

 
 添加进去的1和2,2和3,3和4……两两之间有双向链表,互相记录地址值。遍历的时候也是从1开始遍历。
 
 

TreeSet


 如果字符串里面字母很多,那就从第一个字母开始比较:
 “aaa” > “ab” > “aba” > “cd” > “qwer”
双列集合Map

 ①添加
 
 
②删除
 
 
Map的三种遍历方式:
 
 
 


 

 
 
HashMap

 
 存储的时候只比较键的属性值,如果一样,就要覆盖,这一点和Set不同(Set是不存)! 这就是put里面覆盖的功能!
 
- HashMap底层是哈希表结构的
- 依赖hashCode方法和equals方法保证键的唯一
- 如果键存储的是自定义对象,需要重写hashCode和equals方法
如果值存储自定义对象,不需要重写hashCode和equals方法
LinkedHashMap

 
HashTable(后续补充)
Properties
TreeMap


 这样直接输出已经是升序,如果要降序:
 
Collections 集合工具类

 
 



![【Vitepress报错】Error: [vitepress] 8 dead link(s) found.](https://i-blog.csdnimg.cn/direct/10669360cebb416ca75e0b8736fcb255.png)
![HTB:Squashed[WriteUP]](https://i-blog.csdnimg.cn/direct/b8f1217c48e0470583362a3c45f3b88a.png)










![[前端面试]javascript](https://i-blog.csdnimg.cn/direct/9d8fee457b324159b63978534d6e4dae.png#pic_center)
![[DEBUG] 服务器 CORS 已经允许所有源,仍然有 304 的跨域问题](https://i-blog.csdnimg.cn/direct/eb40cc33f9584adf9d5108e571a23c74.png)


