集合


# 集合

# 特点

  • 数组
    • 有序性:数组中的元素是有序的,通过下标访问,下标从 0 开始
    • 一致性:可以存储基本数据类型、引用数据类型,但数组中所有元素的数据类型相同
    • 不可变性:数组一旦创建,长度不可变
  • 集合
    • 长度可变
    • 对象的容器,存储引用数据类型

Java 集合体系:

接口
实现类
Collection
List
Set
Map
ArrayList
LinkedList
HashSet
TreeSet
HashMap
TreeMap

(集合类体系)

# List 集合

List 集合中,元素是有序的,可以重复出现。

List 集合有两个实现类:

  • ArrayList 集合
    • 又叫数组列表
    • 基于数组结构实现
    • 查询快、增删慢
  • LinkedList 集合
    • 又叫链表
    • 基于链表结构实现
    • 查询慢、增删快

# ArrayList

# 常用方法

# 使用示例

创建集合、添加元素、修改元素、删除元素:

// 创建 ArrayList 集合
ArrayList<String> arrlist = new ArrayList<String>();

// 逐个添加元素
arrlist.add("语文");
arrlist.add("数学");
arrlist.add("英语");
arrlist.add("物理");

// 修改元素:第一个参数是集合中的索引,第二个是要修改的值
arrlist.set(3, "生物"); 

// 拼接两个集合
ArrayList<String> arrlist2 = new ArrayList<String>();
arrlist2.add("高等数学");
arrlist2.add("线性代数");
arrlist2.add("模拟电路");
arrlist2.add("大学英语");
arrlist.addAll(arrlist2);  

// 获取指定索引的元素
System.out.println("first=" + arrlist.get(0));

// 删除集合中指定位置上的某个元素
arrlist.remove(0);
// 删除集合中的某个指定元素
arrlist.remove("数学");
// 删除本集合中的另一个集合
arrlist.removeAll(arrlist2);
1
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

三种方式遍历集合:

/**
 * 使用 foreach 循环遍历
 */
for (String subject : arrlist) {
    System.out.println(subject);
}


/**
 * 使用普通 for 循环进行遍历
 */
for (int i = 0; i < arrlist.size(); i++) {
    subject = arrlist.get(i);
    System.out.println(subject);
}


/**
 * 使用迭代器 (Iterator)
 * 导包:import java.util.Iterator;
 */
Iterator<String> it = arrlist.iterator();
while (it.hasNext()) {
    subject = iterator.next();
    System.out.println(subject);
}
1
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

# LinkedList

# 常用方法

# 使用示例

创建链表、添加元素、修改元素、删除元素:

// 创建 LinkedList 链表
LinkedList<String> lnklist = new LinkedList<String>();

// 逐个添加元素
lnklist.add("数学");
lnklist.add("英语");
// 在链表的开头添加元素
lnklist.addFirst("语文");
// 在链表的结尾添加元素
lnklist.addLast("物理");

// 修改元素:第一个参数是链表中的索引,第二个是要修改的值
lnklist.set(3, "生物"); 

// 拼接两个链表
LinkedList<String> lnklist2 = new LinkedList<String>();
lnklist2.add("高等数学");
lnklist2.add("线性代数");
lnklist2.add("模拟电路");
lnklist2.add("大学英语");
lnklist.addAll(lnklist2);  

// 获取指定索引的元素
System.out.println("first=" + lnklist.get(0));
// 获取链表中的第一个元素
System.out.println("first=" + lnklist.getFirst());
// 获取链表中的最后一个元素
System.out.println("last=" + lnklist.getLast());

// 移除链表开头的元素
lnklist.removeFirst();
// 移除链表结尾的元素
lnklist.removeLast();
1
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

三种方式遍历链表:

// 和 ArrayList 一样,此处省略
1

# Set 集合

Set 集合中的元素,无序不重复、没有索引。

Set 集合有两个实现类:

  • HashSet 集合(非常常用)
    • 元素唯一:插入元素时,HashSet 除了调用 equals() 方法进行比较,还会调用该对象的 hashCode() 来比较 hashCode 值。
    • 元素无序
    • 不是线程安全的,如果有多个线程同时访问或修改同一个 HashSet,必须通过代码来保证同步操作
  • TreeSet 集合
    • 元素唯一:当 TreeSet 集合在保存对象元素时,集合对象必须实现 Comparable 接口,并重写 compareTo 方法,该方法用于排序(>0升序,<0降序)和去重(=0相同对象)
    • 元素有序:因为实现了 SortedSet 接口
    • 提供了高效的元素查找和判断功能

# HashSet

# 常用方法

# 使用示例

创建 HashSet 集合、添加元素、遍历:

// 创建 HashSet 集合
HashSet<String> set = new HashSet<String>();

// 添加元素
set.add("语文");
set.add("数学");
set.add("英语");

// 重复元素无法被添加进去
set.add("语文");
1
2
3
4
5
6
7
8
9
10

集合遍历:

Iterator<String> it = set.iterator();
while (it.hasNext()) {
    // 输出 Set 集合中的每个元素
    System.out.println(it.next()); 
}
1
2
3
4
5

# TreeSet

# 常用方法

# 使用示例

首先设计一个 Account 类,该类要实现 Comparable 接口。

  • 当 TreeSet 集合在保存对象元素时,集合中添加的元素对象必须实现 Comparable 接口,并重写 compareTo 方法。
  • 如果没有实现 Comparable 接口,那么创建 TreeSet 时必须传入一个 Comparator 对象。
/**
 * 实现 Comparable 接口,并重新 compareTo() 方法
 */
public class Account implements Comparable<Account>{
    private String username;
    private String password;
    public Account() {
    }
    public Account(String username, String password) {
        super();
        this.username = username;
        this.password = password;
    }
    
    @Override
    public String toString() {
        return "Account [username=" + username + ", password=" + password + "]";
    }

    // 重写 compareTo() 方法,对 Account 对象进行比较
    @Override
    public int compareTo(Account o) {
        if(!this.username.equals(o.username)) {
        	// 根据用户名及长度进行比较
            return this.username.length() - o.username.length();
        } else {
        	// 根据密码进行比较
            if (this.password.equals(o.password)) {
                return 0;
            } else {
                // 比较用户名的长度
                return this.username.length() - o.username.length();
            }
        }
    }
}
1
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

然后往 TreeSet 集合中添加若干个对象元素,测试 TreeSet 排序功能:

import java.util.TreeSet;

public class TestDemo {
    public static void main(String[] args) {
        // TreeSet 的去重原理
        TreeSet<Account> set = new TreeSet<Account>();
        set.add(new Account("admin", "123"));
        set.add(new Account("demo1", "abc"));
        set.add(new Account("demo2","123"));
        set.add(new Account("demo3","abc"));
        // 如果两个对象的用户名和密码都相等,则认为是两个相同的对象,且按照名字长度升序存放
        for (Account acct: set) {
            System.out.println(acct);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# Map 集合

  • Map 集合以 key-value 形式,存储对象之间的映射关系。
  • 双列集合,由两个集合组成,一个集合保存 Map 中的 key 键,另一个集合保存 value 值。
  • key 无序不重复,value 无序可以重复。

Map 集合有几个常用实现类:

  • HashMap 集合
    • 无序
    • 添加、删除和查找元素都快
  • TreeMap 集合
    • 无序
    • 查找和遍历元素快,添加和删除元素慢
  • LinkedHashMap 集合
    • 有序
  • Hashtable 集合
    • 无序
    • 与 HashMap 相似,但它是线程安全的,因此在多线程环境中性能较低
  • ConcurrentHashMap 集合
    • 无序
    • 与 Hashtable 相似,也是线程安全的,并且性能更高

# HashMap

# 常用方法

# 使用示例

创建 Map 集合对象、添加元素、删除元素、获取元素:

// 使用构造函数创建 HashMap 对象
Map<String, Integer> map = new HashMap<>();

// 添加元素,如果放入重复的 key,新值就会覆盖旧值
map.put("name", "张三");
map.put("age", "13");
map.put("sex", "男");

// 删除元素
map.remove("age");

// 获取元素
String name = map.get("name");              // 如果 key 不存在就返回 null
String sex = map.getOrDefault("sex", "男"); // 如果 key 不存在就返回指定的默认值
1
2
3
4
5
6
7
8
9
10
11
12
13
14

遍历元素,遍历 HashMap 集合的方式和 List 集合不同,需要使用迭代器或者 foreach 循环遍历键值对:

/**
 * 使用 foreach 循环遍历
 */
for (Map.Entry<String, String> entry: map.entrySet()) {    
    String key = entry.getKey();     
    String value = entry.getValue();     
    System.out.println(key + " = " + value); 
}


/**
 * 使用迭代器 (Iterator)
 * 导包:import java.util.Iterator;
 */
// 获取集合中的 entry 条目集合
Set<Entry<String, String>> entrySet = map.entrySet();
// 获取集合中携带的 Iterator 迭代器对象
Iterator<Map.Entry<String, String>> it = entrySet.iterator();
// 通过循环进行迭代遍历
while (it.hasNext()) {     
    // 获取每一个 Entry 条目对象
    Map.Entry<String, String> entry = it.next();    
    / /获取条目中的 key
    String key = entry.getKey();    
    //获取条目中的 value
    String value = entry.getValue();     
    System.out.println(key + " = " + value); 
} 
1
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

# Hashtable

# 常用方法

# 使用示例

创建 Hashtable 集合、存储键值对、获取值:

// 创建 Hashtable 集合
Map<String, Integer> hashtable = new Hashtable<>();

// 存储键值对
hashtable.put("张三", 13);
hashtable.put("李四", 14);
hashtable.put("王五", 15);

// 获取值
int value = hashtable.get("张三");

// 移除键值对
hashtable.remove("李四");

// 清空集合
hashtable.clear(); 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

遍历集合:

for (Map.Entry<String, Integer> entry: hashtable.entrySet()) {
    String key = entry.getKey();
    int value = entry.getValue();
    System.out.println(key + ": " + value);
}
1
2
3
4
5

# ConcurrentHashMap

# 常用方法

# 使用示例

创建 ConcurrentHashMap 集合、存储键值对、获取值:

// 创建 ConcurrentHashMap 集合
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

// 插入元素
map.put("张三", 13);
map.put("李四", 14);
map.put("王五", 15);

// 获取值
Integer value = map.get("张三");

// 移除键值对
map.remove("李四");
1
2
3
4
5
6
7
8
9
10
11
12
13

(完)