Collection集合概述
集合:集合是java中提供的⼀种容器,可以⽤来存储多个数据。
集合和数组既然都是容器,它们有啥区别呢?
数组的⻓度是固定的。集合的⻓度是可变的。
数组中存储的是同⼀类型的元素,可以存储基本数据类型值。集合存储的都是对象。⽽且对
象的类型可以不⼀致。在开发中⼀般当对象多的时候,使⽤集合进⾏存储。
集合框架:
集合按照其存储结构可以分为两⼤类,分别是单列集合 java.util.Collection 和双列集合 java.util.Map 。
Collection:单列集合类的根接⼝,⽤于存储⼀系列符合某种规则的元素,它有两个重要的⼦接⼝,分别是 java.util.List 和 java.util.Set 。
其中, List 的特点是元素有序、元素可重复。 Set 的特点是元素⽆序,⽽且不可重复。 List 接⼝的主要实现类有 java.util.ArrayList 和 java.util.LinkedList
Set 接⼝的主要实现类有 java.util.HashSet 和 java.util.TreeSet 。
Collection 常⽤功能
Collection是所有单列集合的⽗接⼝,因此在Collection中定义了单列集合(List和Set)通⽤的⼀些⽅法,这些⽅法可⽤于操作所有的单列集合。⽅法如下:
public boolean add(E e) //把给定的对象添加到当前集合中 。
public void clear() //清空集合中所有的元素。
public boolean remove(E e) //把给定的对象在当前集合中删除。
public boolean contains(E e) //判断当前集合中是否包含给定的对象。
public boolean isEmpty() //判断当前集合是否为空。
public int size() //返回集合中元素的个数。
public Object[] toArray() //把集合中的元素,存储到数组中
list接⼝介绍
java.util.List 接⼝继承⾃ Collection 接⼝,是单列集合的⼀个重要分⽀,习惯性地会将实现了 List 接⼝的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以⼀种线性⽅式进⾏存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有⼀个特点就是元素有序,即元素的存⼊顺序和取出顺序⼀致
ArrayList集合
java.util.ArrayList 集合数据存储的结构是数组结构。元素增删慢,查找快,由于⽇常开发中使⽤最多的功能为查询数据、遍历数据,所以 ArrayList 是最常⽤的集合。
LinkedList集合
java.util.LinkedList 集合数据存储的结构是链表结构。⽅便元素添加、删除的集合。
LinkedList是⼀个双向链表,那么双向链表是什么样⼦的呢,我们⽤个图了解下
实际开发中对⼀个集合元素的添加与删除经常涉及到⾸尾操作,⽽LinkedList提供了⼤量⾸尾操作的⽅法。这些⽅法我们作为了解即可:
public void addFirst(E e) //将指定元素插⼊此列表的开头。
public void addLast(E e) //将指定元素添加到此列表的结尾。
public E getFirst() //返回此列表的第⼀个元素。
public E getLast() //返回此列表的最后⼀个元素。
public E removeFirst() //移除并返回此列表的第⼀个元素。
public E removeLast() //移除并返回此列表的最后⼀个元素。
public E pop() //从此列表所表示的堆栈处弹出⼀个元素。
public void push(E e) //将元素推⼊此列表所表示的堆栈。
public boolean isEmpty() //如果列表不包含元素,则返回true。
LinkedList是List的⼦类,List中的⽅法LinkedList都是可以使⽤,这⾥就不做详细介绍,我们只需要了解LinkedList的特有⽅法即可。
Set接⼝
java.util.Set 接⼝和 java.util.List 接⼝⼀样,同样继承⾃ Collection 接⼝,它与Collection 接⼝中的⽅法基本⼀致,并没有对 Collection 接⼝进⾏功能上的扩充,只是⽐Collection 接⼝更加严格了。与 List 接⼝不同的是, Set 接⼝中元素⽆序,并且都会以某种规则保证存⼊的元素不出现重复。
Tips:Set集合取出元素的⽅式可以采⽤:迭代器、增强for。
HashSet
不能保证元素的排列顺序,顺序有可能发生变化
不是同步的
集合元素可以是null,但只能放入一个null
当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。
简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相 等
注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对 象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。
TreeSet
TreeSet 是一个有序的集合,它的作用是提供有序的Set集合, 它继承于AbstractSet抽象类,实现了NavigableSet,Cloneable,java.io.Serializable接口
源码摘抄:
java.lang.Object
↳ java.util.AbstractCollection<E>
↳ java.util.AbstractSet<E>
↳ java.util.TreeSet<E>
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable{}
TreeSet 继承于AbstractSet,所以它是一个Set集合,具有Set的属性和方法。
TreeSet 实现了NavigableSet接口,意味着它支持一系列的导航方法。比如查找与指定目标最匹配项。
TreeSet 实现了Cloneable接口,意味着它能被克隆。
TreeSet 实现了java.io.Serializable接口,意味着它支持序列化。
TreeSet是基于TreeMap实现的。TreeSet中的元素支持2种排序方式:自然排序 或者 根据创建TreeSet 时提供的 Comparator 进行排序。这取决于使用的构造方法。
TreeSet是非同步的。 它的iterator 方法返回的迭代器是fail-fast的
(01) TreeSet是有序的Set集合,因此支持add、remove、get等方法。
(02) 和NavigableSet一样,TreeSet的导航方法大致可以区分为两类,一类时提供元素项的导航方法,返回某个元素;另一类时提供集合的导航方法,返回某个集合。
lower、floor、ceiling 和 higher 分别返回小于、小于等于、大于等于、大于给定元素的元素,如果不存在这样的元素,则返回 null。
TreeSet遍历方式 <TreeSet不支持快速随机遍历,只能通过迭代器进行遍历!>
1 Iterator顺序遍历
for(Iterator iter = set.iterator(); iter.hasNext(); ) {
iter.next();
}
2 Iterator顺序遍历
// 假设set是TreeSet对象
for(Iterator iter = set.descendingIterator(); iter.hasNext(); ) {
iter.next();
}
3 for-each遍历HashSet
// 假设set是TreeSet对象,并且set中元素是String类型
String[] arr = (String[])set.toArray(new String[0]);
for (String str:arr)
System.out.printf("for each : %s\n", str);
map集合<Map与Collection在集合框架中属并列存在>
Map是一种依照键(key)存储元素的容器,键(key)很像下标,在List中下标是整数。在Map中键(key)可以使任意类型的对象。Map中不能有重复的键(Key),每个键(key)都有一个对应的值(value)。
一个键(key)和它对应的值构成map集合中的一个元素。
Map中的元素是两个对象,一个对象作为键,一个对象作为值。键不可以重复,但是值可以重
常用方法:
返回值 方法 说明
V put(K key, V value) 添加键值对, 并返回value+
V get(Object key) 根据key获取指定的value
void clear(); 清空Map所有的键值对
V remove(Object key) 删除指定的键值对并返回其value
boolean isEmpty() 是否为空
int size() 键值对的个数
boolean containsKey(Object key) 是否包含指定key
boolean containsKey(Object key) 是否包含指定的Value
boolean equals(Object obj) 比较和其他Map是否相等
int hashCode() 获取Map在内存中对应的哈希值
Collection values(); 把map中所有的value存到一个集合中并返回这个集合
Set keySet() 把Map中的所有key存到一个Set集合中, 并返回
Set<Map.Entry<K, V>> entrySet() 把Map中的所有键值对(Entry对象)存入Set集合
map集合和collection集合的区别:
- Map一次存一对元素, Collection 一次存一个。Map 的键不能重复,保证唯一。
- Map存储元素使用put方法,Collection使用add方法
- Map集合没有直接取出元素的方法,而是先转成Set集合,在通过迭代获取元素
- Collection是单列集合, Map 是双列集合。
Map学习体系:
—| Map 接口 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
—| HashMap 采用哈希表实现,所以无序
—| TreeMap 可以对健进行排序
—|Hashtable:
底层是哈希表数据结构,线程是同步的,不可以存入null键,null值。
效率较低,被HashMap 替代。
—|HashMap:
底层是哈希表数据结构,线程是不同步的,可以存入null键,null值。
要保证键的唯一性,需要覆盖hashCode方法,和equals方法。
—| LinkedHashMap:
该子类基于哈希表又融入了链表。可以Map集合进行增删提高效率。
—|TreeMap:
底层是二叉树数据结构。可以对map集合中的键进行排序。需要使用Comparable或者Comparator 进行比较排序。return 0,来判断键的唯一性。
HashMap:
HashMap底层是一个Entry数组(默认大小为16),当存放数据时会根据hash算法计算数据的存放位置。算法:hash(key)%n,n就是数组的长度。
当计算的位置没有数据时,就直接存放,当计算的位置有数据时也就是发生hash冲突的时候/hash碰撞时,采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。
这使得HashMap的查询效率非常高
实现原理图:
java.util.HashMap<k,v>集合 implements Map<k,v>接口
HashMap集合的特点:
1.HashMap集合底层是哈希表:查询的速度特别的快
JDK1.8之前:数组+单向链表
JDK1.8之后:entry数组+单向链表|红黑树(链表的长度超过8):提高查询的速度
2.hashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致
java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
LinkedHashMap的特点:
1.LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
2.LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的
TreeMap
底层是二叉树(红黑树)数据结构。
特点:线程不同步,可以同时给Map集合中的键进行排序。