文章目录
开局一张图:整个集合大家庭!
Collection
是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素。JDK不提供此接口的任何直接实现。Collection主要包括List和Set。
创建Collection集合的对象:
- 多态的方式
- 具体实现类如 ArrayList 等
1.常用方法
有一些增删查改的方法
方法 | 含义 |
---|---|
boolean add(E e) | 添加元素 |
boolean remove(object o) | 从集合中移除指定元素 |
void clear( ) | 清除集合中的元素 |
boolean contains(Object o) | 判断集合中是否存在指定的元素 |
boolean isEmpty( ) | 判断集合是否为空 |
int size() | 集合的长度 |
2.遍历
(为方便后面演示,首先新建一个Collection集合,再往里面添加元素)
Collection<String> sites = new ArrayList<String>();
sites.add("Google");
sites.add("baidu");
sites.add("Taobao");
(注意多态的创建方法,sites对象调用方法时编译看左边,运行看右边,这样就用不了子类特有方法,参考链接:实现和继承时的java多态)
(1)for循环
// 常规的写法
for(int i=0;i<sites.size();i++) {
// get()是List接口定义,ArrayList实现的方法
System.out.println(sites.get(i));
}
(2)Iterator
Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。它不是一个集合,仅用于遍历集合。
所有实现了Collection接口的集合类都有一个iterator()方法(通过集合对象去调用iterator()方法),用以返回Iterator接口的对象。
Iterator iterator() :返回此集合的迭代器,通过集合的iterator()方法得到
Iterator iterator = coll.iterator()
(coll是集合的对象)
主要方法:
方法 | 含义 |
---|---|
boolean hasNext() | 检测集合中是否还有元素 |
E next() | 返回迭代器的下一个元素,并且更新迭代器的状态 |
void remove() | 将迭代器返回的元素删除 |
先用hasNext()
方法判断,再调用next()
方法
// 创建集合 sites 的迭代器
Iterator<String> it = sites.iterator();
// 通过对象it的next方法,输出集合中的第一个元素
System.out.println(it.next());
// 先判断集合中是否还有元素,如果有,进行遍历
while(it.hasNext())
{
String s = it.next();
System.out.println(s);
}
(3)增强for循环
- 实现Iterable接口的类允许其对象成为增强型for语句的目标;
- 内部原理是个Iterator迭代器(简化版的Iterator);
- 简化数组和Collection集合的遍历
格式:
for(元素数据类型 变量名:数组或Collection集合)
{
// 使用变量,变量即元素!
}
// s 即 sites 中的元素
for (String s : sites) {
System.out.println(s);
}
3.List
特点:
- 是一个接口,继承自Collection,不能实例化,需要具体类来实例化;
- List 集合中的对象有序(添加顺序和取出顺序一致),且可重复;
- List集合每一个元素都有其对应的顺序索引,可以通过整数索引访问元素(丰富了Collection方法)
List 接口常用实现类有:ArrayList(实现动态数组),Vector(实现动态数组)LinkedList(实现链表),Stack(实现堆栈)。
相比Collection增加的方法(List特有方法):
方法 | 含义 |
---|---|
void add(int index,E e) | 【增】在此集合的指定位置插入指定元素 |
E remove(int index) | 【删】删除指定索引处的元素,返回被删除的元素 |
E set(int index,E e) | 【改】修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 【查】返回指定索引处的元素 |
int indexOf(Object o) | 返回此列表中指定元素的第一次出现的索引 |
(方法演示见下面的ArrayList)
特有遍历——列表迭代器 ListIterator,
- 通过List集合的ListIterator得到,
ListIterator<E> listIterator()
- 允许程序沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置。
- 主要方法
方法 | 含义 |
---|---|
E next() | 返回迭代器的下一个元素 |
boolean hasNext() | 检测集合中是否还有元素 |
E previous() | 返回迭代器的上一个元素 |
void add(E e) | 将指定元素插入列表 |
(1)ArrayList
特点:
-
ArrayList 类实现一个可增长的动态数组,它可以存储不同类型的对象(包括 null 在内),而数组只能存放特定数据类型的值。
-
ArrayList 实现了 List 接口,底层数据结构是数组,查询快,增删慢。存储类型只能存储引用数据类型。
定义形式:
// E: 泛型数据类型,用于设置 objectName 的数据类型
ArrayList<E> objectName =new ArrayList<>(); // 初始化
常用方法:
实现了List接口的方法,没有太多特有方法,这里直接代码演示:
//创建集合
ArrayList<String> list = new ArrayList<>();
//public boolean add(E e):添加元素,返回是否添加成功
list.add("apple");
list.add("pear");
list.add("apple"); // 注意集合具有无序 可重复性
list.add("watermelon");
//输出集合
System.out.println("list:" + list); //输出 list:[apple, pear, apple, watermelon]
//public int size():返回集合中的元素的个数
System.out.println("集合的长度是:"+list.size()); // 输出:集合的长度是:4
增删查改:
/*public E set(int index,E element):修改指定索引处的元素,返回被修改的元素*/
System.out.println(list.set(1,"grape")); // 输出pear
//System.out.println(list.set(3,"hello")); // 越界错误
/*public E get(int index):返回指定索引处的元素*/
System.out.println(list.get(1)); // 输出grape
/*public boolean remove(Object o):删除指定的元素,返回删除是否成功*/
System.out.println(list.remove("apple")); // 输出true
System.out.println(list.remove("hello")); // 输出false
System.out.println("list:" + list);// 输出:list:[grape, apple, watermelon]
/*public E remove(int index):删除指定索引处的元素,返回被删除的元素*/
System.out.println(list.remove(1)); // 输出apple
ArrayList基本概念和方法使用基本就是这样,进一步可以参考ArrayList源码分析,可以看到底层扩容原理
(2)LinkedList
特点:
- LinkedList底层维护了一个双向链表,查询慢,增删快;
- LinkedList中维护了两个属性first和last,分别指向首节点和尾节点;
- 可作为队列使用,可进行列表的相关操作
实现的接口和继承的类如下:
![](https://img-blog.csdnimg.cn/a761d43ee01143dea05f9b646b2541b8.png)
相对于List的一些特有功能:
方法 | 含义 |
---|---|
void addFirst(E e) | 在该列表开头插入指定的元素 |
void addLast(E e) | 将指定元素追加到此列表的末尾 |
E getFirst() | 返回该列表中的第一个元素 |
E getlast() | 返回该列表中的最后一个元素 |
E removeFirst() | 从列表中删除并返回第一个元素 |
E removeLast() | 从列表中删除并返回最后一个元素 |
(3)两个实现类的比较
底层结构 | 增删效率 | 改查效率 | |
---|---|---|---|
ArrayList | 可变数组 | 较低,通过数组扩容 | 较高 |
LinkedList | 双向链表 | 较高,通过链表追加 | 较低 |
4.Set
特点:
- Set 的元素是无序的(添加和取出的顺序不一致)
- Set 不包含重复元素的 collection,则最多包含一个null
- Set集合没有带索引的方法,不能用普通for循环遍历(迭代器,增强for)
Set中的方法和Collection中的类似。
(1)HashSet
特点:
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证(不保证存储和取出的元素顺序一致)
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
定义:
HashSet<String> sites = new HashSet<String>();
代码演示:
// "static void main" must be defined in a public class.
public class Main {
public static void main(String[] args) {
// 1. initialize the hash set
Set<Integer> hashSet = new HashSet<>();
// 2. add a new key
hashSet.add(3);
hashSet.add(2);
hashSet.add(1);
// 3. remove the key
hashSet.remove(2);
// 4. check if the key is in the hash set
if (!hashSet.contains(2)) {
System.out.println("Key 2 is not in the hash set.");
}
// 5. get the size of the hash set
System.out.println("The size of has set is: " + hashSet.size());
// 6. iterate the hash set
for (Integer i : hashSet) {
System.out.print(i + " ");
}
System.out.println("are in the hash set.");
// 7. clear the hash set
hashSet.clear();
// 8. check if the hash set is empty
if (hashSet.isEmpty()) {
System.out.println("hash set is empty now!");
}
}
}
介绍一下哈希值:
哈希值是jdk根据对象的地址或字符串或数字计算出来的int类型的数值。
Object类中的方法:
public int hashCode():返回对象的哈希值
String s="hello";
System.out.println(s.hashCode());
Student std = new Student();
System.out.println(std.hashCode());
99162322
1784662007
一般来说,不同对象的哈希值是不同的,但是可以通过方法重写使不同对象的哈希值相同。
哈希表:
jdk8以前,底层采用数组+链表实现,可以看作一个元素为链表的数组
关于HashSet更深入的底层原理,请参见 HashSet底层原理
(2)TresSet
Map
Interface Map<K,V> K:键的类型,V:值的类型
将键映射到值的对象,Map中的key不允许重复(原因和HashSet一样)不能包含重复的键,value可以重复。每个键可以映射到最多一个值。
创建Map集合的对象
- 多态的方式
- 具体实现类如HashMap
1.Map的常用方法
基本功能
方法 | 含义 |
---|---|
V put(K key,V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度 |
获取功能
方法 | 含义 |
---|---|
V get(Object key) | 根据键获取值 |
V getOrDefault(Object key, V defaultValue) | 获取key的value,如果不存在,就得到默认值 |
Set keySet() | 获取所有键的集合 |
Collection values() | 获取所有值的集合 |
Set<Map.Entry<K,V>> entrySet() | 获取所有键值对对象的集合 |
2.遍历
因为Map存储的元素都是成对出现的,将Map看成一个“夫妻对”的集合
方式1
遍历思路:先把所有的丈夫给集中起来;然后遍历丈夫的集合,获取到每一个丈夫;最后根据丈夫去找对应的妻子
步骤:
- 获取所有键的集合,用
keySet()方法
实现 - 遍历键的集合,获取到每一个键
- 根据键去找值,用
get(Object key)
方法实现
方式2
遍历思路:先获取所有“结婚证”的集合,然后遍历结婚证的集合,得到每一个结婚证,最后根据结婚证获取丈夫和妻子
步骤:
- 获取所有键值对对象的集合
- Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
- 遍历键值对对象的集合,得到每一个键值对对象
- 用增强for实现,得到每一个Map.Entry
- 根据键值对对象获取键和值
- 用getKey()得到键
- 用getValue()得到值
3.HashMap
以一个例子熟悉一下方法:
public static void main(String[] args) {
// 1. initialize a hash map
Map<Integer, String> hashmap = new HashMap<>();
// 2. insert a new (key, value) pair or update the value of existed key
hashmap.put(201, "张三");
hashmap.put(202,"李四");
hashmap.put(203, "王五");
hashmap.put(201, "赵六"); // 注意此时key重复了,不会被添加到hashmap中
// 4. get the value of specific key
System.out.println("The value of key 201 is: " + hashmap.get(1));
// 5. delete a key
hashmap.remove(202);
// 6. check if a key is in the hash map
if (!hashmap.containsKey(202)) {
System.out.println("Key 2 is not in the hash map.");
}
// 7. get the size of the hash map
System.out.println("The size of hash map is: " + hashmap.size());
// iterate the hash map
// 8-1 获取所有键的集合。用keySet()方法实现
Set<String> keySet = hashmap.keySet();
//遍历键的集合,获取到每一个键。用增强for实现
for (String key : keySet) {
//根据键去找值。用get(Object key)方法实现
String value = hashmap.get(key);
System.out.println(key + "," + value);
}
// 8-2 获取所有键值对对象的集合
Set<Map.Entry<Integer, String>> entrySet = hashmap.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for (Map.Entry<Integer, String> me : entrySet) {
//根据键值对对象获取键和值
String key = me.getKey();
String value = me.getValue();
System.out.println(key + "," + value);
}
// 9. clear the hash map
hashmap.clear();
// 10. check if the hash map is empty
if (hashmap.isEmpty()) {
System.out.println("hash map is empty now!");
}
}
}
关于HashMap的底层原理,请参见: HashMap源码分析
4.TreeMap
Collections
此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。它包含在 collection 上操作的多态算法,即“包装器”,包装器返回由指定 collection 支持的新 collection,以及少数其他内容。即相当于Array与Arrays类,都是工具类,用来操作相应的容器。
常用方法:
方法 | 含义 |
---|---|
reverse(List) | 反转List中元素的顺序 |
shuffle(List) | 打乱List中元素的顺序 |
sort(List) | 对List中元素进行排序 |
swap(List,int,int) | 交换list中的两处元素 |