Java集合
一、集合概述
1、集合的定义
集合:集合是Java中提供的一种容器,可以用来存储多个数据。
2、集合和数组的比较
相同点:都是容器,可以用来存储多个数据。
不同点:
(1)数组的长度是固定的;集合的长度是可变的。
(2)数组中存储的是同一类型的元素,可以存储基本数据类型值。集合中存储的都是对象,而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。
3、集合的分类
集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection
和双列集合java.util.Map
。
二、Iterator迭代器
1、Iterator接口
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.Iterator
。Iterator
接口也是Java集合中的一员,但它与Collection
、Map
接口有所不同,Collection
接口与Map
接口主要用于存储元素,而Iterator
主要用于迭代访问(即遍历)Collection
中的元素,因此Iterator
对象也被称为迭代器。
2、使用迭代器遍历Collection集合
首先要获取集合对应的迭代器,用来遍历集合中的元素。接着在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续再判断,如果还有就再取出来。一直把集合中的所有元素全部取出为止。
举例:
Collection<String> c = ...;
Iterator<String> it = c.iterator();
while(it.hasNext()){
String element = it.next();
System.out.println(element);
}
3、使用增强for循环遍历数组和Collection集合
增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合。它的内部原理其实也是一个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
举例:
for(String element : c){
System.out.println(element);
}
三、单列集合Collection接口
1、Collection接口概述
Collection
接口是单列集合的根接口。在Collection
接口定义着单列集合框架中最最共性的内容。它有两个重要的子接口,分别是java.util.List
和java.util.Set
。其中,List
的特点是元素有序、元素可重复。Set
的特点是元素无序,而且不可重复。List
接口的主要实现类有java.util.ArrayList
和java.util.LinkedList
;Set
接口的主要实现类有java.util.HashSet
和java.util.TreeSet
。
2、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()
: 把集合中的元素,存储到数组中。
3、List接口
(1)List接口的特点
1)它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照 11、 22、33的顺序完成的。
2)它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
3)集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
(2)List接口的常用方法
List接口作为Collection接口的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法,如下:
-
public void add(int index, E element)
: 将指定的元素,添加到该集合中的指定位置上。 -
public E get(int index)
:返回集合中指定位置的元素。 -
public E remove(int index)
: 移除列表中指定位置的元素, 返回的是被移除的元素。 -
public E set(int index, E element)
:用指定元素替换集合中指定位置的元素,返回的是更新前的元素。
(3)List接口的实现类
1)ArrayList集合
ArrayList集合实现的数据结构是数组。
2)LinkedList集合
LinkedList集合实现的数据结构是双向链表。(在Java中,所有的链表实际上都是双向链表)
在实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而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集合也常作为堆栈,队列的结构来使用。
4、Set接口
(1)Set接口的特点
java.util.Set
接口和 java.util.List
接口一样,同样继承自 Collection
接口,它与 Collection
接口中的方法基本一致,并没有对 Collection
接口进行功能上的扩充,只是比 Collection
接口更加严格了。与 List
接口不同的是,Set
接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
(2)Set接口的实现类
1)HashSet集合
HashSet 是根据对象的哈希值 来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元 素唯一性的方式依赖于: hashCode 与 equals 方法。
【注】如果我们往集合中存放的是自定义的对象,那么要保证其唯一,就必须重写hashCode和equals方法建立 属于当前对象的比较方式。(在IDEA中可以使用快捷方式直接生成代码)
底层原理:
java.util.HashSet
底层的实现其实是一个 java.util.HashMap
的支持。HashSet集合实现的数据结构是 哈希表。在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的元素都存储在 一个链表里。 但是当位于一个链表中的元素较多时,即hash值相等的元素较多时,通过key值依次查找的效率 降低。而在JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红 黑树,这样大大减少了查找的时间。
2)LinkedHashSet集合
我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,就需要使用在 HashSet下面有的一个子类 java.util.LinkedHashSet
,它是链表和哈希表组合的一个数据存储结构。
四、集合工具类Collections
1. 常用方法
-
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中添加一些元素。 -
public static void shuffle(List<?> list)
:打乱顺序 :打乱集合顺序。 -
public static <T> void sort(List<T> list)
:将集合中元素按照默认规则排序。 -
public static <T> void sort(List<T> list,Comparator<? super T> )
:将集合中元素按照指定规则排序。
2. 使用Comparator比较器实现自定义排序
举例:
public class CollectionsDemo3 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("cba");
list.add("aba");
list.add("sba");
list.add("nba");
//排序方法 按照第一个单词的降序
Collections.sort(list, new Comparator<String>() {
//@Override
public int compare(String o1, String o2) {
return o2.charAt(0) ‐ o1.charAt(0);
}
});
System.out.println(list);
}
}
结果如下
[sba, nba, cba, aba]
五、双列集合Map接口
1. Map接口概述
现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等, 这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即 java.util.Map
接口。
2. Map接口和Collection接口的比较
-
Collection 中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。
-
Map 中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的 值。
-
Collection 中的集合称为单列集合, Map 中的集合称为双列集合。
-
需要注意的是, Map 中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
3. Map接口的常用方法
-
public V put(K key, V value)
: 把指定的键与指定的值添加到Map集合中。 -
public V remove(Object key)
: 把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值。 -
public V get(Object key)
:根据指定的键,在Map集合中获取对应的值。 -
public Set<K> keySet()
: 获取Map集合中所有的键,存储到Set集合中。 -
public Set<Map.Entry<K,V>> entrySet()
: 获取到Map集合中所有的键值对对象的集合(Set集合)。
4. Map集合的遍历
(1)键找值方式
步骤:
1. 获取Map中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键。方法提示: keyset() 。
2. 遍历键的Set集合,得到每一个键。
3. 根据键,获取键所对应的值。方法提示: get(K key) 。
举例:
public class MapDemo01 {
public static void main(String[] args) {
//创建Map集合对象
HashMap<String, String> map = new HashMap<String,String>();
//添加元素到集合
map.put("胡歌", "霍建华");
map.put("郭德纲", "于谦");
map.put("薛之谦", "大张伟");
//获取所有的键 获取键集
Set<String> keys = map.keySet();
// 遍历键集 得到每一个键
for (String key : keys) {
//key 就是键
//获取对应值
String value = map.get(key);
System.out.println(key+"的CP是:"+value);
}
}
}
(2)利用Entry键值对对象
步骤:
1. 获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。方法提示: entrySet() 。
2. 遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
3. 通过键值对(Entry)对象,获取Entry对象中的键与值。 方法提示: getkey() 、getValue() 。
举例:
public class MapDemo02 {
public static void main(String[] args) {
// 创建Map集合对象
HashMap<String, String> map = new HashMap<String,String>();
// 添加元素到集合
map.put("胡歌", "霍建华");
map.put("郭德纲", "于谦");
map.put("薛之谦", "大张伟");
// 获取所有的entry对象 entrySet
Set<Entry<String,String>> entrySet = map.entrySet();
// 遍历得到每一个entry对象
for (Entry<String, String> entry : entrySet) {
// 解析
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"的CP是:"+value);
}
}
}
5. Map接口的实现类
1)HashMap集合
存储数据采用的哈希表结构,元素的存取顺序不能保证一致。
【注】当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须重写对 象的hashCode和equals方法(回忆HashSet存放自定义对象)。
2)LinkedHashMap集合
HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素 的存取顺序一致;通过哈希表结构可以保证键的唯一、不重复。