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
