基础——集合

一、集合和数组的区别

1. 数组:

(1) 长度不可变
(2) 可以是任意类型

2. 集合

(2) 长度可变
(3) 引用类型

二、集合的关系结构

在这里插入图片描述
列出了最常使用的集合接口和实现类的关系。

三、java.util.Collection:接口

单列集合的根接口,里面定义的方法,子接口和实现类都有。

常用方法

  1. public boolean add(E e) : 把给定的对象添加到当前集合中 。
  2. public boolean contains(Object obj) : 判断当前集合中是否包含给定的对象。
  3. public boolean isEmpty() : 判断当前集合是否为空。
  4. public int size() : 返回集合中元素的个数。
  5. public boolean remove(E e) : 把给定的对象在当前集合中删除。
  6. public Object[] toArray() : 把集合中的元素,存储到数组中
  7. public void clear() :清空集合中所有的元素。
  • 注意事项:
  1. Collection中没有定义索引,因为List有索引,而Set是没有索引的,索引仅仅是List接口的特性。
  2. toArray方法返回的是Object数组,需要强制类型转换调用子类特有方法
    解决:使用迭代的方法
  • 并不是所有的集合都有索引,以前使用for+get方法索引,没了索引就不行了。jdk提供了一中遍历集合的通用方式那就是使用迭代器java.util.Iterator<E>

    tip: 详细方法使用和其他方法详见API文档学习。

四、java.util.List:接口

继承自java.util.Collection接口

1、特点

  1. 保证存入元素一次进来的顺序
  2. 有索引,实现类可以通过成员方法get(int index)访问指定位置的元素
  3. 存入的元素可重复

2、常用方法

List继承了Collection集合的全部方法,同时还有自己的特有方法

  • 特有方法:
  1. public void add(int index, E element) : 将指定的元素,添加到该集合中的指定位置上。
  2. public E get(int index) :返回集合中指定位置的元素。
  3. public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。
  4. public E set(int index, E element) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素

3、实现类

1、java.util.ArrayList

(1)底层原理
  1. 底层是数组实现
    a.每次先开辟一个定长为10的数组空间
    b.如果空间不够,在开辟一个1.5倍原本长度+1的数组空间,c.把当前数组拷贝进去,最后销毁原本的数组
    d.并且让集合对象指向新的数组。

  2. 删除元素的原理
    a.查找元素是否存在
    b.存在,记录索引
    c.创建一个新数组
    d.把剩余元素拷贝进入新数组
    e.数组变量指向新的数组地址
    f.销毁老数组所占的内存空间

(2)特点
  1. 查询速度快,增删快
  2. 底层是数组结构
  3. 查询快的原因:有索引,元素内存分布连续
  4. 线程不同步–不安全–效率高
(3)拓展了解
`java.util.Vector<E>:`(基本已经不用)
	1.底层也是数组结构
	2.线程同步--安全--但是效率低下

2、java.util.LinkedList

(1)特点

  1. 查询慢,增删快
  2. 底层是链表结构
  3. 线程不同步–不安全–效率高

(2)特有方法

  1. void addFirst​(E e) 在该列表开头插入指定的元素。

  2. void addLast​(E e) 将指定的元素追加到此列表的末尾。

  3. E getFirst​() 返回此列表中的第一个元素。

  4. E getLast​() 返回此列表中的最后一个元素。

  5. E removeFirst​() 从此列表中删除并返回第一个元素。

  6. E removeLast​() 从此列表中删除并返回最后一个元素。

  7. LinkedList集合中,具有栈结构特点(先进后出)的方法
    public E pop​() 从此列表表示的堆栈中弹出一个元素。
    public void push​(E e) 将元素推送到由此列表表示的堆栈上。

五、 java.util.Set:接口

继承自java.util.Collection接口

1、特点

  1. 无索引
  2. 集合内元素唯一

2、常用实现类

(1)java.util.HashSet

特点
  1. 无索引
  2. 集合内元素唯一
  3. 不保证存入和取出的顺序是一致的
  4. 底层数据结构:哈希表——数组 + 链表(节点数>8–红黑树)

(2)java.util.LinkedHashSet

特点
  1. 无索引
  2. 集合内元素唯一
  3. 存入和取出是有序的
  4. 底层数据结构:哈希表 + 链表
    哈希表:保证数据的唯一(同HashSet)
    链表:保证数据是有序的

3、集合内部保证元素唯一性的原理

根本原因:java.lang.Object类中带有hashCode方法。

hashCode方法

  1. 返回该对象的哈希码值(int类型)
  2. Object的hashCode方法,根据对象的地址值计算出一个int数字,叫做哈希码值(哈希地址值
  3. 所以只要new对象,就会产生新的地址,因此哈希值也就不同

注意事项:

  1. 子类不重写hashCode方法,调用Object类的hashCode方法,根据对象地址值计算哈希值。
  2. 子类根据地址值计算哈希值没有意义,需要根据内容计算哈希值。
  3. 由于new对象,就会产生新的地址,因此哈希值也就不同,自定义类要实现存入Set集合保证唯一就必须要重写hashCode方法和equals方法。
  4. 根据String的代码测试,发现String覆盖重写hashCode方法,重写方式:根据String中每个字符的ASCII码值通过一个算法进行相加的出哈希值。只要是算法就会存在缺陷。

出现内容不同哈希值相同的情况

System.out.println("重地".hashCode()); // 1179395
System.out.println("通话".hashCode()); // 1179395

总结–根据内容计算哈希值

  1. 哈希值不同内容一定不相同
  2. 哈希值相同,内容可能不相同,因此还需要调用equeals方法进行内容的判断。

为什么需要hashCode方法?

为了在使用哈希表的时候能减少equals方法的调用,提高效率。

4、hashSet存储元素的原理(重点!)

(1)哈希表结构图
在这里插入图片描述

(2)HashSet存储原理流程图
在这里插入图片描述
(3)实例流程图
在这里插入图片描述
注:
【1】加载因子:说明什么时候数组(table)进行扩容,0.75说明数组(table)的使用比例大于0.75就进行扩容,扩容为原来的2倍。

总结

Set集合接口所有实现类保证元素唯一:依赖于hashCode方法和equals方法。
存入Set集合的元素要保证唯一必须覆写hashCode方法和equals方法。

六、List与Set的转换

  1. List与Set接口的实现类都有方法:boolean addAll​(Collection<? extends E> c)可以实现两种接口集合的转换。
  2. List与Set接口的实现类都有构方法:ArrayList​(Collection<? extends E> c)LinkedList​(Collection<? extends E> c)、HashSet​(Collection<? extends E> c)和LinkedHashSet​(Collection<? extends E> c)可以实现两种接口类型的转换。

使用场景:

需求一:

要求把List集合中元素去重
1.按顺序
2.不按顺序

解决方案:

  • 四种方法:
    1、新建一个列表,元素依次加入并使用contains()方法判断是否已经存在,新数组中不存在就加入,存在就舍弃。
    2、List数据一个个加入到Set
    3、Set直接用addAll(Collection< E> c)
    4、Set构造方法Set(Collection< E> c)

需求二:
要求把Set集合按从小到大排序

分析与解决方案
我们知道Set集合是没有sort方法的,并且Collections工具类中的sort方法也是支持List接口的实现子类。
由于List的构造方法可以接受的是Collection c 参数,所以也可以把Set转换成List,之后使用collections工具类排序

七、集合工具类:java.util.Collections

  • 特点
  1. 构造方法私有
  2. 全部是静态方法
  • 常用方法:
  1. public static void addAll(List<?> list,T ... elements):把元素集合加入到指定集合list
  2. public static void shuffle(List<?> list):打乱集合内元素
  3. pubiic static <T> void sort(List<T> list,comparator<? super T> comp):把指定集合进行排序(可自定义排序)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章