UM2L14——集合类
UM2L14——集合类
Java中各集合类之间的关系
Java 中的集合类就类似 C# 中的 List 和 Dictionary 的存在
主要用于批量存储对象,并且可以动态添加,动态删除
Java 的集合类继承关系如下:
Collection(接口):
- 
Set(接口)- 
HashSet - 
TreeSet 
 - 
 - 
List(接口)- 
ArrayList - 
LinkedList 
 - 
 
Map(接口):
- 
HashMap - 
TreeMap 
Collection 接口中的方法
- 
add(E e) 添加元素 - 
remove(Object o) 移除元素 - 
clear() 清空元素 - 
isEmpty() 是否为空 - 
iterator() 获取迭代器,可以用于遍历 - 
size() 集合中元素个数 - 
contains() 判断元素是否存在 - 
toArray() 将容器中元素转为数组 
List 接口中的方法
由于 Java 不存在索引器,因此,需要使用 get 和 set 来通过索引获取和修改元素
- 
get(int index) 获取指定位置元素 - 
set(int index, Object obj) 修改集合中指定位置的元素 
ArrayList 和 LinkedList 类
Java 中的 ArrayList 和 LinkedList 类似于 C# 中的 List 和 LinkedList
根据自己的实际情况选择使用即可
两者方法上的使用完全一致,因为他们继承相同的接口,区别:
- 
ArrayList 本质是数组,是顺序存储 - 
LinkedList 本质是链表,是链式存储 
两者性能上的区别:
- 
LinkedList 在插入删除时效率高于ArrayList - 
ArrayList 在访问集合中指定位置对象时效率高于LinkedList 
常用方法
- 
初始化
两种
List都非常类似C#中的List1
2
3ArrayList<String> list = new ArrayList<>();
ArrayList<Integer> list2 = new ArrayList<>();
LinkedList<String> linkedList = new LinkedList<>(); - 
增
add()1
2
3
4
5
6list.add("1");
list.add("2");
list.add("3");
list2.add(1);
list2.add(2);
list2.add(3); - 
删
remove()clear()
ArrayList 和LinkedList 使用remove来移除某个元素可以通过索引,也可以通过值来移除
但是,如果我们的容器当中存储的是****int类型 在移除的时候,我们只能通过索引移除而无法通过指定值来移除某个元素还有一个
Clear方法来清空列表1
2
3
4list.remove("3");
list.remove(1);
list2.remove(1);
list.clear(); - 
查
contains()get()1
2
3
4
5System.out.println(list2.get(0));
System.out.println(list2.get(1));
if (list2.contains(3))
System.out.println("存在2元素");输出:
1
2
31
3
存在2元素 - 
改
set()1
2list2.set(0, 99);
System.out.println(list2.get(0));输出:
1
99
 - 
判断是否为空
isEmpty()1
2
3
4
5if (list.isEmpty())
System.out.println("列表为空1");
list.clear();
if (list.isEmpty())
System.out.println("列表为空2");输出:
1
列表为空2
 - 
遍历
iterator()对
ArrayList 和LinkedList的遍历有三种方法:- 
for循环遍历索引 - 
for循环遍历元素 - 迭代器遍历
 
1
2
3
4
5
6
7
8
9
10
11
12
13//for循环遍历索引
for (int i = 0; i < list2.size(); i++) {
System.out.println(list2.get(i));
}
//for循环遍历元素
for (Integer i : list2) {
System.out.println(i);
}
//迭代器遍历
Iterator<Integer> it = list2.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}输出:
1
2
3
4
5
699
3
99
3
99
3 - 
 - 
转数组
toArray()如果直接调用
toArray()而不传入参数,返回的是Object[](即使使用了泛型去声明列表,返回的还是Object[])
可以提前声明对应类型的数组,将其传入到toArray()内,该数组就会接收列表转数组的结果1
2
3
4
5
6
7
8
9
10
11
12System.out.println("**********");
Object[] objs = list2.toArray();
for (Object x : objs) {
System.out.println(x);
}
System.out.println("**********");
Integer[] ints = new Integer[2];
list2.toArray(ints);
for (int x : ints) {
System.out.println(x);
}输出:
1
2
3
4
5
6**********
99
3
**********
99
3 
HashSet 和 TreeSet 类
Set相关集合的特点是:
- 不会存储重复元素,如果我们有去重需求可以选择他们
 - 只能遍历获取所有元素,不能单独获取中间的某个元素
 - 
TreeSet会自动排序,可以取出(弹出)首尾 
- 
相同点:他们都不允许存储重复的元素,如果传入重复的只会记录一个
他们相对上节课的
ArrayList 和LinkedList 最大的使用区别就是他们可以去除重复的元素
都不能像ArrayList 和LinkedList 通过索引获取或修改元素 - 
不同点:他们的底层数据结构不同,
HashSet 底层结构是哈希表,TreeSet 底层结构是树
TreeSet 是有序排列的(会自动将加入元素进行排序),HashSet 不一定有序
TreeSet 相对HashSet 由于多继承了SortedSet 接口,所以有更多的方法可以使用 
注意:TreeSet具有排序功能
元素是数字时,按照大小升序排列,元素是字符串时,按照字符的编码值升序排列
元素是自定义类时,可以继承Comparable接口 重载其中的方法
特别是compareTo方法,它用于制定排序规则
常用方法
TreeSet 和 HashSet 都没有改的功能,因为他们没有继承list接口
- 
初始化
1
2HashSet<Integer> hashSet = new HashSet<>();
TreeSet<Integer> treeSet = new TreeSet<>(); - 
增
add()1
2
3
4treeSet.add(3);
treeSet.add(2);
treeSet.add(1);
treeSet.add(0); - 
删
remove()这两个容器都没有通过索引去移除的重载,因此只能通过值移除某个元素
1
treeSet.remove(0);
 - 
查
contains()1
2
3
4if (treeSet.contains(1))
System.out.println("存在1元素");
if (treeSet.contains(0))
System.out.println("存在0元素");输出:
1
存在1元素
 - 
遍历
iterator()只有两种遍历:
for循环遍历元素和迭代器值得一提的是,
TreeSet 是有序排列的(会自动将加入元素进行排序),HashSet 不一定有序1
2
3
4
5
6
7
8
9
10
11treeSet.add(3);
treeSet.add(2);
treeSet.add(1);treeSet.add(1);treeSet.add(1);treeSet.add(1);
for (int x : treeSet) {
System.out.println(x);
}
Iterator<Integer> it = treeSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}输出:
1
2
3
4
5
61
2
3
1
2
3通过遍历结果可以发现,
set集合会自动去重 
TreeSet独有的方法
- 
first() 返回当前第一个元素1
2//treeSet: 1,2,3
System.out.println(treeSet.first()); - 
pollFirst() 取出当前第一个元素取出和获取是不一样的,取出是获取该元素的同时让该元素被移除出该
set1
2
3
4
5
6//treeSet: 1,2,3
System.out.println(treeSet.pollFirst());
System.out.println("**********");
for (int x : treeSet) {
System.out.println(x);
} - 
last() 返回最后一个元素1
2//treeSet: 2,3
System.out.println(treeSet.last());输出:
1
3
 - 
pollLast() 取出当前最后一个元素1
2
3
4
5
6//treeSet: 2,3
System.out.println(treeSet.pollLast());
System.out.println("**********");
for (int x : treeSet) {
System.out.println(x);
}输出:
1
2
33
**********
2 - 
headSet(E obj) 返回一个新Set集合,新集合是 截取 传入的值对应的元素 前面的所有的元素(不包括传入的值)1
2
3
4
5
6//treeSet: 1,2,3,4
SortedSet<Integer> newSet = treeSet.headSet(3);
//newSet: 1,2
for (int x : newSet) {
System.out.println(x);
}输出:
1
21
2 - 
subSet(E b, E e) 返回一个新Set集合,新集合是 截取 传入的值b 和e 对应的元素之间的所有对象,左包含,右不包含1
2
3
4
5//treeSet: 1,2,3,4
SortedSet<Integer> newSet2 = treeSet.subSet(1, 4);
for (int x : newSet2) {
System.out.println(x);
}输出:
1
22
3 - 
tailSet(E obj) 返回一个新Set集合,新集合是传入对象(包含)之后的所有对象1
2
3
4
5//treeSet: 1,2,3,4
SortedSet<Integer> newSet3 = treeSet.tailSet(2);
for (int x : newSet3) {
System.out.println(x);
}输出:
1
2
32
3
4 
Map接口
Map集合类似C#中的Dictionary字典,以键值对形式存储数据
我们在使用时,建议主要使用HashMap,它的效率高于TreeMap
- 
put(K key, V value) 添加键值对 - 
containsKey(Object key) 判断是否存在键 - 
containsValue(Object value) 判断是否存在值 - 
get(Object key) 如果存在key,则返回对应值,否则返回null - 
keySet() 返回该集合中的所有key对象形成的Set集合 - 
values() 返回该集合中所有value对象形成的Collection集合 - 
size() 键值对 对数 - 
isEmpty() 是否为空 - 
remove(Object key) 根据键移除 - 
clear() 清空容器 
HashMap和TreeMap之间的区别
- 
相同点:他们都是以键值对形式存储数据,方法使用基本相同
 - 
不同点:
- 
HashMap允许有null键和null值(但是必须保持键的唯一性)
TreeMap不允许键为空 - 
TreeMap中的映射关系具有一定的顺序,它会帮助我们进行排序
因此在添加、删除、定位映射关系时,效率较HashMap差 - 
HashMap数据结构基于哈希表,TreeMap数据结构基于树 
 - 
 
在实际使用时,建议都使用HashMap,除非需要排序的Map时才用TreeMap
HashMap和TreeMap中的常用方法
- 
初始化
1
HashMap<Integer, String> hashMap = new HashMap<>();
 - 
增
put()1
2
3hashMap.put(1, "123");
hashMap.put(2, "234");
hashMap.put(3, "345"); - 
删
remove()1
hashMap.remove(3);
 - 
查
get()containsKey()需要传入键来获取值,如果不存在这个键,则返回
null1
2
3
4
5
6System.out.println(hashMap.get(1));
System.out.println(hashMap.get(3));
if (hashMap.containsKey(1))
System.out.println("存在键1");
if (hashMap.containsValue("123"))
System.out.println("存在值\"123\"");输出:
1
2
3
4
5
123
null
存在键1
存在值"123" - 
改
put()containsKey()修改
HashMap或TreeMap的值时,直接使用put来修改值就可以了
一般如果是明确要修改某个存在的键对应的值,而非添加键值对,就需要配合containsKey方法来修改1
2
3if (hashMap.containsKey(1))
hashMap.put(1, "555");
System.out.println(hashMap.get(1)); - 
遍历
keySet()values()遍历可以遍历键,也可以遍历值
1
2
3
4
5
6for (Integer i : hashMap.keySet()) {
System.out.println(hashMap.get(i));
}
for (String str : hashMap.values()) {
System.out.println(str);
}输出:
1
2
3
4555
234
555
234 
