Collection集合
Collection接口
概述
数组和集合都是Java中提供的容器
集合: 英文译为 Collection,用来存放对象的容器,集合中可以存放不同类型的对象,并且集合的长度可变。
在编程时,常常需要集中存放多个数据,可以使用数组来保存多个对象,但数组长度不可变化,一旦在初始化数组时指定了数组长度,这个数组长度就是不可变的,如果需要保存数量变化的数据,数组就有点无能为力了;
为了保存数量不确定的数据,以及保存具有映射关系的数据,Java提供了集合类。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。
小结: 集合和数组的对比:
- 数组中的元素可以基本类型的值,也可以是对象; 而集合中只能保存对象
- 数组一旦指定了长度,长度就不能再改变; 而集合的长度是可以随时改变的
- 往数组中插入元素非常麻烦,需要将插入位置后面的元素往后移动; 或者删除数组中间位置的某一个元素, 需要将删除位置后的元素往前移动; 而如果往集合中插入元素或者删除集合中的某一个元素,直接使用现成的方法操作即可
集合的继承结构
由于需求不同,Java就提供了不同的集合类。这多个集合类的数据结构不同,但是它们都是要提供存储和遍历功能的,我们把它们的共性不断的向上提取,最终就形成了集合的继承体系结构图。
Collection接口
- List接口
- ArrayList类
- LinkedList类
- Set接口
- HashSet类
- TreeSet类
解释说明:
Collection集合是所有单值集合的顶层接口, 其中定义了常用的用于操作集合以及集合中元素的方法
例如: 添加元素、删除元素、获取元素、获取集合长度、判断功能、将集合转成数组、迭代器遍历元素等功能
List是Collection的子接口,特点是其中的元素是有序的(即:元素存入集合时的顺序和取出的顺序一致)
可以通过下标访问List中的元素,另,List集合中的元素是可以重复的(包括null)
Set也是Collection的子接口,特点是其中的元素是无序(即:元素存入集合时的顺序和取出的顺序不一定一致)
无法通过下标访问Set中的元素,另外,Set集合中的元素是不可以重复的
学习集合的建议:
学习接口中提供的共性方法
通过实现类创建对象, 调用这些共性方法
常用方法
!!boolean add(E e)
- 往集合中添加指定元素e
boolean addAll(Collection c)
- 将小集合添加到大集合中
!!boolean isEmpty()
- 如果集合中没有任何元素(空集合), 返回true
boolean contains(Object o)
- 如果此集合中包含指定元素o, 则返回true
boolean containsAll(Collection c)
- 如果此集合中包含指定 集合c 中的所有元素,则返回 true。
- 例如c1中有 “a”,”b”,”c”,”d”, 而c2中有”a”,”b”, 则c1包含c2, 返回true
若,c1中有 “a”,”b”,”c”,”d”, 而c2中有”x”,”a”,”b”, 则c1不包含c2, 返回false
!!int size()
- 返回集合的大小(元素个数)
!!boolean remove(Object o)
- 从集合中删除指定的元素o, 删除成功则返回true
- 如果删除的元素不存在导致删除失败, 则返回false
- 如果元素o在集合中出现多次,仅删除第一个
boolean removeAll(Collection c)
- 删除此集合中那些也包含在指定集合c中的所有元素, 若有共同元素, 则删除并返回true
例如 c1中有 “a”,”b”,”c”,”d”, 而c2中有”x”,”a”,”b”,
c1.removeAll(c2),只删除c1中两个共同的元素 “a”,”b”, 对c2没有影响
- 如果两个集合中没有共同元素, 则不删除, 返回false
boolean retainAll(Collection c)
- 仅保留此集合中那些也包含在指定集合c中的元素
- 例如 c1中有 “a”,”b”,”c”,”d”, 而c2中有”x”,”a”,”b”,
c1.retainAll(c2),只保留c1中两个共同的元素 “a”,”b”, 对c2没有影响
void clear()
- 删除此集合中的所有元素
Object[] toArray()
- 将此集合转成对象数组
boolean equals(Object o)
- 比较此 collection 与指定对象是否相等。
!!Iterator
- 返回此集合中所有元素组成的迭代器。
实例1:CollectionDemo1
1 | package collection; |
实例2:CollectionDemo2
1 | package collection; |
Point1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47package pojo;
import java.util.Objects;
public class Point {
private int x;
private int y;
//alt+insert
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public String toString() {
return "(" + x + "," + y +")";
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return x == point.x && y == point.y;
}
public int hashCode() {
return Objects.hash(x, y);
}
}
实例4:CollectionDemo4
1 | package collection; |
集合的遍历
IteratorDemo1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author 老安
* @data 2022/7/18 20:00
* 集合的遍历
* Collection层面上不支持随机访问操作(根据指定的位置获取对应的元素),但是集合的子类是支持的,我们后面学习
* 而Collection层面上想要取出集合的元素只能通过遍历集合,从而拿出集合中的每一个元素
* 集合提供了统一遍历的方式:迭代器遍历模式
* 对应方法:
* Iterator iterator()
* 该方法会返回一个用于遍历当前集合的迭代器对象
*/
public class IteratorDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("a");
c.add("#");
c.add("b");
c.add("#");
c.add("c");
c.add("#");
c.add("d");
c.add("#");
c.add("e");
System.out.println(c);
/*
* 迭代器使用方式:
* */
//1:获取要遍历的集合的迭代器对象
Iterator it = c.iterator();
//2:问(问集合是否有下一个元素可以遍历)
/*
* boolean hasNext()
* 判断集合是否有下一个元素可以遍历
* 迭代器的起始位置是集合的第一个元素之前,因此第一次调用hasNext()就是判断集合是否有第一个元素
* */
while (it.hasNext()){
//3:取(取出下一个元素)
/*
* E next()
* 取出集合中的下一个元素,获取元素后,迭代器的位置会向后移动一个元素的位置
* */
String e = (String) it.next();
if ("#".equals(e)){
//4:删(删除集合中的指定元素)
/*
* 迭代器在遍历的过程中,不能通过集合的方法来增删元素,
* 但是可以通过迭代器的方法来删元素
* 迭代器提供了remove()方法,该方法会将本次next()取出的元素从集合中删除
* */
//c.remove(e);
it.remove();
}
}
System.out.println(c);
}
}
## 增强型for循环
**NewForDemo**
```JAVA
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author 老安
* @data 2022/7/18 20:24
* JDK5推出时,推出了一个新的特性:增强型for循环
* 通常也称之为叫做新循环和foreach循环
* 新循环不会取代传统for循环的操作,它的出现仅仅是为了使用相同的语法去遍历集合和数组
* 语法:
* for(元素类型 e : 集合或者数组){
* <p>
* }
*/
public class NewForDemo {
public static void main(String[] args) {
String[] array = {"a", "b", "c", "d", "e"};
//传统for循环
//array.fori
for (int i = 0; i < array.length; i++) {
String s = array[i];
System.out.println(s);
}
//新循环 array.for
for (String s : array) {
System.out.println(s);
}
/*
* 集合之所以能够装载所有类型的元素,是因为集合装载的类型是Object类型
* 集合和数组一样,一般情况下,都装载同一类型元素
* 集合的泛型可以约束集合中装载的元素类型是什么
* */
Collection<String> c = new ArrayList<>();
c.add("A");//编译器会检查传入的参数是否是泛型的指定的类型
c.add("B");
c.add("C");
c.add("D");
c.add("E");
//c.for
//新循环就是迭代器遍历
for (String s : c) {
System.out.println(s);
}
}
}
List集合
概述
List是一个有序的Collection(List是Collection的子接口),使用此接口能够精确的控制每个元素插入的位置,能够通过索引(类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。
List 接口存储一组可重复、有序(插入顺序)的对象。
特点
- 元素有下标,可以通过下标访问元素
- 元素是有序的(存入集合的顺序和取出的顺序一定相同)
- 元素可以重复(包括null)
List方法测试
ListDemo1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52package collection;
import java.util.ArrayList;
import java.util.List;
/**
* @author 老安
* @data 2022/7/18 21:22
* java.util.List接口
* List继承自Collection,是最常用的一类集合.特点:可以存放重复的元素且有序
* List里提供了一套可以通过下标操作元素的方法
* 常用实现类:
* java.util.ArrayList:内部使用数组实现,查询性能更好
* java.util.LinkedList:内部使用链表实现,增删性能更好
* 对性能没有特别苛刻的要求下,通常使用ArrayList即可
*/
public class ListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
System.out.println(list);
//获取集合中的第三个元素
/*
* E get(int index)
* 获取指定下标对应的元素
* */
String str = list.get(2);
System.out.println(str);
//通过下标来遍历集合
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
//新循环遍历一定是从头到尾都遍历一次
for (String s : list) {
System.out.println(s);
}
/*
* E set(int index,E e)
* 将给定的元素设置到集合的指定的位置,返回值为该位置原来的元素
* 替换元素的操作
* */
//给集合list的下标1的位置设置新的元素f,将被替换的b返回
String old = list.set(1, "f");
System.out.println(old);
System.out.println(list);
}
}
ListDemo2
1 | package collection; |
ListDemo3
1 | package collection; |
集合和数组的转换
集合转换数组:CollectionToArrayDemo1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
/**
* @author 老安
* @data 2022/7/20 20:51
* 将一个集合转换为数组
*/
public class CollectionToArrayDemo {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
c.add("A");
c.add("B");
c.add("C");
c.add("D");
c.add("E");
System.out.println("集合:"+c);
/*
* toArray由于默认是Object类型,所以使用非常少,
* 一般都使用他的重载方法toArray(Object[] arr)
* 要生成什么类型的数组,arr就声明什么类型,并且数组的长度,
* 一般都指定成集合的元素数量
* */
String[] array = c.toArray(new String[c.size()]);
System.out.println("数组:"+ Arrays.toString(array));
}
}
数组转换集合: ArrayToListDemo1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40package collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author 老安
* @data 2022/7/20 20:59
* 数组转换为集合
*/
public class ArrayToListDemo {
public static void main(String[] args) {
String[] arr = {"A","B","C","D","E"};
System.out.println("数组:"+Arrays.toString(arr));
//数组转换为集合的方法
List<String> list = Arrays.asList(arr);
System.out.println("集合:"+list);
//对list集合的操作,同时也会更改arr数组
list.set(1, "F");
System.out.println("数组:"+Arrays.toString(arr));
System.out.println("集合:"+list);
arr[0] = "G";
System.out.println("数组:"+Arrays.toString(arr));
System.out.println("集合:"+list);
/*
* 由于集合和数组关联了,而且数组是定长的,所以给集合中新增元素,
* 同时也会给数组新加元素,但是数组不能新加,就会报错
* */
//list.add("H");
//List<String> list2 = new ArrayList<>();
//list2.addAll(list);
//创建集合,并且将list集合的元素装载到list2中
List<String> list2 = new ArrayList<>(list);
list2.add("H");
System.out.println("数组:"+Arrays.toString(arr));
System.out.println("集合:"+list);
System.out.println("集合:"+list2);
}
}
集合的排序
SortListDemo1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27package collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
/**
* @author 老安
* @data 2022/7/20 21:12
*/
public class SortListDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 10; i++) {
//生成一个随机整数
int a = random.nextInt(100);
list.add(a);
}
System.out.println("乱序集合:"+list);
Collections.sort(list);//会自然排序,从小到大
System.out.println("从小到大集合:"+list);
Collections.reverse(list);//反转集合的元素
System.out.println("从大到小集合:"+list);
}
}
Map接口
概述
Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的键(key)另外一组值用于保存Map里的值(value),键和值是一一对应的关系,称为映射。根据键就能找到对应的值,类似于生活中一张身份证对应一个人一样。
Map的key和value可以是任何引用类型的数据,其中key不允许重复,同一个Map对象的任何两个key通过equals方法比较总是返回false。
特点
- Map集合中每个元素都有两个值, 分别是key(键) 和 value(值)
- Map集合中的key(键)不允许重复, 在第二次添加已有的key时, value会被会覆盖
- Map集合中的元素是无序的(即元素存入集合的顺序和取出时的顺序很可能不一致)
- Map集合中的key和value具有映射关系, 可以通过key(键)来获取对应的value(值)
key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的、确定的value。从Map中取出数据时,只要给出指定的key,就可以取出对应的value。
如果把Map里的所有key放在一起来看,它们就组成了一个Set集合(所有的key没有顺序,key与key之间不能重复),实际上Map确实包含了一个keySet()方法,用于返回Map里所有key组成的Set集合。
如果把Map里的所有value放在一起来看,它们又非常类似于一个List:元素与元素之间可以重复,每个元素可以根据索引来查找,只是Map中的索引(也就是key)不是从0开始的整数值,而是任意类型的对象;
如果需要从List集合中取出元素,则需要提供该元素的数字索引;如果需要从Map中取出元素,则需要提供该元素的key。因此,Map有时也被称为字典,或关联数组。
继承结构
Map接口
- HashMap类
- TreeMap类
- Hashtable类
解释说明:
Map集合是采用键-值对(key-value)的存储方式, 键(key)、值(value)可以是引用类型的数据, key不允许重复, vaue可以重复, key和value是一对一的关系, 通过指定的key总能找到唯一的、确定的value值
HashMap 和 Hashtable 都是Map接口的实现类,它们之间的关系完全类似于ArrayList和Vector的关系
- HashMap是线程不安全的, 所以HashMap的性能要比HashTable高一些
- HashMap可以使用null作为key或value, Hashtable不允许使用null作为key和value;
- Hashtable是一个古老的Map实现类,JDK 1.0出现,出现时,Java还没有提供Map接口,命名没有遵守Java的命名规范,与Vector类似的是,尽量少用Hashtable实现类,即使需要创建线程安全的Map实现类,也无须使用Hashtable实现类,可以通过别的方式来解决线程安全问题。
- TreeMap是Map的子接口SortedMap的的实现类, 是可以支持对内部元素进行排序的类, 也正因为如此, TreeMap的执行效率通常要比HashMap和HashTable慢。
MapDemo
1 | package map; |
变量分析
1 | package test; |