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#中的List
1
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()
取出当前第一个元素取出和获取是不一样的,取出是获取该元素的同时让该元素被移除出该
set
1
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()
需要传入键来获取值,如果不存在这个键,则返回
null
1
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