Java 集合是一种非常常用的容器,就像数组那样,是为了储存各种各样的数据类型或者数据结构而设计的。其包含了各种已经封装好的数据结构,比如栈,队列,封装好的“数组”等等。

Collection 接口

Collection 接口是最为基本的集合接口,也是相对比较高级的接口,其下又实现了一些子接口。

Set 子接口

Set 子接口最显著的特征就是置入其中的数据是“无序”且不可重复的。这种无序指的是其中存储的数据可能并不是按照你输入的顺序存储的,而是以其独有的方式进行排列的。而 Set 中的一些数据结构,是直接利用了 Map 中的数据结构实现的。

HashSet

HashSet 虽然是基于 HashMap 实现的,但其最底层所应用的便是我们数据结构中所学习的哈希表,有也就是说其底层实际上是利用哈希函数存储的,而这样的存储方式,也使得其查找,插入,删除等操作的时间复杂度可以降为 \(\Theta (1)\)

常见操作的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) {
HashSet<Integer> hashSet = new HashSet<>();
hashSet.add(1);
hashSet.add(2);
hashSet.add(3);
hashSet.add(1);

System.out.println(hashSet.size());
hashSet.clear();
System.out.println(hashSet.size());
}

// 运行结果:可以看出其不可重复
// 3
// 0
TreeSet

同样,TreeSet 也是基于 TreeMap 实现的,但其最底层所使用的便是我们数据结构没学的红黑树 ,由于其底层是利用红黑树实现的,所以其可以有序取出,存进去的元素可以以由大到小,或者由小到大的顺序逐个取出,由于是树形结构,所以其查取的时间复杂度是 \(O(logN)\)

常见操作的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<>();

treeSet.add(1);
treeSet.add(2);
treeSet.add(3);
treeSet.add(1);

while (!treeSet.isEmpty()) {
System.out.println(treeSet.size() + " " + treeSet.first());
treeSet.remove(treeSet.first());
}
}

// 运行结果:可以看出其不可重复,并且按由小到大的顺序排列了
// 3 1
// 2 2
// 1 3
EnumSet

枚举集合,暂时还没用过,所以先列出来,待补……

List 子接口

Set 相反,List 子接口是“有序”可重复的。

ArrayList

相当于一个可变数组(内部也是数组实现的),但是其是不同步的,也就是说其不是线程安全的!

常见操作的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) {
ArrayList<Integer> array = new ArrayList<>();

array.add(1);
array.add(2);
array.add(3);
array.add(1);

System.out.println(array.size());
for (int i:array) {
System.out.println(i);
}
}

// 运行结果:可以看出其是可重复,并且是按照输入顺序的
// 4
// 1
// 2
// 3
// 1
LinkedList

相当于一个可变数组(内部也是链表实现的),但是其是不同步的,也就是说其不是线程安全的!

常见操作的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();

list.add(1);
list.add(2);
list.add(3);
list.add(1);

System.out.println(list.size());
for (int i:list) {
System.out.println(i);
}
}

// 运行结果同 ArrayList,不赘述
Stack

栈类,不多赘述!

常见操作的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();

stack.push(1);
stack.push(2);
stack.push(3);
stack.push(1);

System.out.println(stack.size());
while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
}

// 运行结果:正常的栈!只是 Stack是 push 和 pop
// 4
// 1
// 3
// 2
// 1
Vector

可变数组,实现了 List 接口,线程安全的,但是没有 ArrayList 类快!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) {
Vector<Integer> vector = new Vector<>();

vector.add(1);
vector.add(2);
vector.add(3);
vector.add(1);

System.out.println(vector.size());
for (int i:vector) {
System.out.println(i);
}
}

// 运行结果同 ArrayList,不赘述

Queue 子接口 和 Deque 子接口

队列接口和双端队列接口

LinkedList

如上述,不赘述!

Map 接口

具有映射关系的 key-value 对的集合。

HashMap

无序存放,key 不允许重复,基于哈希表 Map 接口的实现。

常见操作的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();

map.put("文盲", 100);
map.put("李四", 100);
map.put("张三", 100);
map.put("文盲", 70);
map.put(null, null);

System.out.println(map.size());
for (Map.Entry<String, Integer> entry: map.entrySet()) {
System.out.println("key = " + entry.getKey() + ",Value = " + entry.getValue());
}
}

// 运行结果:可见 key 不能重复,但是后面的会将前面的覆盖。同时key可以为null
// 3
// key = null,Value = null
// key = 李四,Value = 100
// key = 张三,Value = 100
// key = 文盲,Value = 70
HashTable

无序存放,key 不允许重复。但是,与 HashMap 不同的是,不允许存在 nullkeyvalue,并且是线程安全的!

常见操作的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) {
Hashtable<String, Integer> map = new Hashtable<>();

map.put("文盲", 100);
map.put("李四", 100);
map.put("张三", 100);
map.put("文盲", 70);
map.put(null, null);

System.out.println(map.size());
for (Map.Entry<String, Integer> entry: map.entrySet()) {
System.out.println("key = " + entry.getKey() + ",Value = " + entry.getValue());
}
}

// 运行结果:空指针异常,可见不可为 null!取消之后正常
// java.lang.NullPointerException
TreeMap

有序map

常见操作的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) {
TreeMap<String, Integer> map = new TreeMap<>();

map.put("John", 100);
map.put("Ali", 100);
map.put("Bob", 100);
map.put("John", 70);
map.put("Lily", null);

System.out.println(map.size());
for (Map.Entry<String, Integer> entry: map.entrySet()) {
System.out.println("key = " + entry.getKey() + ",Value = " + entry.getValue());
}
}

// 运行结果:key不能为null。同时可见是有序的,
// 4
// key = Ali,Value = 100
// key = Bob,Value = 100
// key = John,Value = 70
// key = Lily,Value = null

Iterator 接口

迭代接口,可用来遍历所有集合类的数据!

常见操作的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) {
HashSet<Integer> hashSet = new HashSet<>();

hashSet.add(1);
hashSet.add(2);
hashSet.add(3);
hashSet.add(4);

Iterator<Integer> it = hashSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}