# finally -> 03 【List、Set】
## 1.常用实现类
### 1.1 java.util.List
java.util.List是Collection接口的子接口,特点:
1. 可以存储重复元素
2. 有先后顺序
3. 有索引值
##### 常用的实现类有:
1. ArrayList:底层使用的是数组。查找快,增删慢。
2. LinkedList:底层使用的是链表。增删快,查找慢。
3. Vector:底层使用的也是数组,和ArrayList基本一样,不过线程安全。
##### Collection接口的方法,我都有。但是我还有自己`特有`的方法:
public void add(int index, E element):添加一个元素到指定的索引位置。
public E remove(int index):根据指定的索引值删除一个元素,返回被删除的元素。
public E set(int index, E replacement):根据指定的索引值,替换一个元素,返回被替换掉的元素。
public E get(int index):根据指定的索引值获取一个元素。
增删改查:CRUD Create Read Update Delete
### 1.2 LinkedList
ArrayList底层使用数组,空间连续,查找快,增删慢。
LinkedList底层使用链表,空间不连续,增删快,查找慢。
Vector底层也是数组,和ArrayList基本一样,但是线程安全,性能低。
##### LinkedList当中特有的方法:
public void addFirst(E e):在开头添加一个元素
public void addLast(E e):在末尾添加一个元素
public E getFirst():获取开头的元素
public E getLast():获取末尾的元素
public E removeFirst():删除开头的元素
public E removeLast():删除末尾的元素
##### LinkedList当中有两个与栈相关的方法:
public void push(E e):压栈、进栈,在左边添加一个元素。相当于addFirst方法。
public E pop():弹栈、出栈,在左边删除并取出一个元素。相当于removeFirst方法。
对于这两个方法来说,数据元素的出入口全都是左边。
### 1.3 java.util.set
java.util.Set是Collection的子接口。特点:
1. 不允许重复元素
2. 不保证先后顺序
3. 没有索引值
##### 常用子类:
1. HashSet:速度特别快,不保证顺序。
2. LinkedHashSet:速度也很快,但是还能额外保证顺序。
3. TreeSet:有大小排序功能。
`注意`:先后顺序和大小排序是不一样的!
##### HashSet集合是最常使用的Set集合,特点:
因为底层使用了一种名叫“哈希表”的数据结构,所以查找元素的速度嗷嗷快。
底层原理其实是在复用HashMap(明天学习)。
#### 【重点问题】
HashSet是如何判断元素是否重复的?如何得知集合当中是否已经存在了重复的元素?
两个对象是否相同,由equals和hashCode两个方法共同决定。
## 2.hashCode
### 2.1来自java.lang.Object当中的方法:
public int hashCode():根据当前对象,产生一个“哈希值”(对象的特征码)
如果没有覆盖重写hashCode方法,那么Object当中的hashCode将会在JVM当中:
默认使用对象的内存地址值参与运算,然后得到一个与地址相关的int数字:哈希值。
只要内存够用,可以创建很多个对象,无数个不同的地址值。
默认的哈希值只是使用了地址值参与运算而已,并不直接等于地址值。
无数种地址 --> 哈希运算hashCode() --> 42亿种int哈希值
意味着:可能有不一样的对象,哈希值是相同的。
如果自己编写hashCode和equals方法,必须同时满足3+5条原则。
##### hashCode方法的三条原则:
1. 运行期一致性。
2. 对象相同,那么哈希值必须相同。
3. 对象不同,那么哈希值不一定相同。
##### equals方法的五条原则:
1. `自反性`:自己和自己比较,一定相同。
2. `对称性`:A比较B,B比较A,效果一样。
3. `传递性`:如果AB一样,并且BC一样,那么AC也一样。
4. `一致性`:只要对象的内容不变,比较的结果就不能变。
5. `非空性`:任何对象和null值比较,一定是false。
- 如果在哈希结构当中存储自定义的类型,那么必须覆盖重写equals和hashCode方法。
- LinkedHashSet是HashSet的子类。
底层其实也有哈希表,速度也比较快,但是额外还添加了一层双向链表,用来专门维护顺序。
### 2.2 可变参数
可变参数就是参数的类型统一,但是个数随意。是Java 5添加的特性之一。
##### 格式:
修饰符 返回值类型 方法名称(参数类型... 参数名称) {
方法体
}
##### `注意事项`:
1. 可变参数只是一个语法糖,底层其实就是普通的数组。
2. 方法的可变参数只能有一个
3. 方法的可变参数只能是最后一个
## 3.collections工具类
### 3.1常用的静态方法
Collections是与集合相关的工具类,其中有常用的静态方法:
public static void `shuffle`(List<?> list):打乱集合当中的顺序。
public static boolean `addAll`(Collection c, T... elements):
第一个参数代表加到哪个集合中,第二个可变参数代表需要添加的元素都是谁。
public static void `sort`(List list):按照自然顺序进行大小排序
public static void sort(List list, Comparator comp):第二个参数代表排序的规则。
### 3.2 两个排序区别
public static void sort(List list, Comparator comp):第二个参数代表排序的规则。
##### 口诀:
1. 对于Comparable来说:升序就是我减他
2. 对于Comparator来说,升序就是一减二