Java集合用法(附25道练习题)

Java集合框架是一组接口和类,用于表示和操作集合,允许我们以各种方式存储和操作对象组。Java集合框架主要分为两大类:Collection接口和Map接口。下面从这两方面介绍,并介绍常用的集合类,如ArrayList,HashSet和HashMap


目录

一、Collection接口

1. 常用的Collection衍生接口或类

(1)List接口

(2)Set接口

(3)Queue接口 

(4)Deque接口

2. Collection接口常用的方法(通用方法)

(1)添加元素

(2)删除元素

(3)检查元素

(4)获取大小

(5)转换为数组

(6)迭代器

(7)流操作

(8)其他

(9)示例代码

3. ArrayList

(1)特点

(2)常用方法

① 构造方法

② 元素添加

③ 元素删除

④ 元素修改

⑤ 元素查询

⑥ 转换操作

⑦ 视图和迭代器

⑧ 大小和容量

⑨ 其他

(3)示例代码

4. HashSet

(1)特点

(2)常用方法

① 构造函数

② 增加元素

③ 删除元素

④ 查找元素

⑤ 其他方法

(3)示例代码

二、Map接口

1. 常用的Map衍生类

(1)HashMap类 

(2)LinkedHashMap类 

(3)TreeMap类 

(4)Hashtable类 

(5)ConcurrentHashMap类 

2. HashMap

(1)特点

(2)常用方法

① 构造函数

② 增删改查和遍历

③ 获取key和value

④ Stream流

⑤ 其他方法

(3)示例代码

三、集合练习

1. ArrayList

(1)定义一个ArrayList,并添加以下元素:1, 2, 3, 4, 5。然后使用循环遍历并打印所有元素。

(2)移除索引为2的元素,并输出修改后的ArrayList。

(3)给定一个包含整数的ArrayList,编写一个方法来计算所有元素的和。

(4)给定一个包含字符串的ArrayList,编写一个方法来删除所有包含字母“b”的字符串。

(5)将ArrayList反转,并输出反转后的ArrayList。(使用Collections)

(6)给定一个包含整数的ArrayList,编写一个方法来找出最大的元素。

(7)给定两个包含整数的ArrayList,编写一个方法来合并这两个ArrayList,并去除重复元素,并进行排序。

(8)给定一个整型ArrayList {10, 20, 30, 40, 50},请找出数字30的索引位置,并输出结果。

(9)给定一个整型ArrayList {1, 2, 3, 4, 5},将其每个元素乘以2,并输出结果。

(10)Collections练习

2. HashSet

(11)判断HashSet中是否包含某个元素。

(12)从HashSet中删除一个元素,并输出删除后的HashSet。

(13)遍历HashSet中的所有元素。

(14)创建一个HashSet,移除所有偶数。

(15)给定两个HashSet,创建一个方法来计算它们的并集。

(16)给定一个整数数组,去除重复元素,并按降序排列。

3. HashMap

(17)创建一个HashMap,并添加5个键值对,然后遍历并打印所有键值对。

(18)检查HashMap中是否包含某个键或值?

(19)从HashMap中删除所有值为null的键值对。

(20)给定一个整数数组,找出数组中每个元素对应出现次数。

(21)合并两个HashMap,如果键相同,则将对应的值相加。

(22)反转HashMap中的键和值。

(23)将一个整数数组中的元素按照其出现的次数降序排序。

(24)找出两个HashMap中共有的键(键的交集)。

(25)输出一个Map中最小和最大的Key。


进阶知识:Stream API

可参考 Stream API 详解和25道练习题-CSDN博客

一、Collection接口

1. 常用的Collection衍生接口或类

(1)List接口

它扩展了Collection接口,用于存储有序集合,允许重复元素。常用实现类有:

  • ArrayList: 使用动态数组实现,适合频繁的查找和更新操作。
  • LinkedList: 使用双向链表实现,适合频繁的插入和删除操作。

(2)Set接口

它也扩展了Collection接口,用于存储无序集合,不允许重复元素。常用实现类有:

  • HashSet: 基于哈希表实现,存储无序集合。
  • LinkedHashSet: 保持插入顺序的哈希表实现。
  • TreeSet: 基于红黑树实现,元素按照自然顺序或者Comparator排序。

(3)Queue接口 

用于存储待处理的元素序列,按照特定的顺序处理它们。常用实现类有:

  • PriorityQueue: 一个基于优先级堆的无界优先队列。
  • LinkedList: 也可以用作Queue的实现。

(4)Deque接口

双端队列,允许元素从两端被添加或移除。常用实现类有:

  • ArrayDeque: 使用循环数组实现。

2. Collection接口常用的方法(通用方法)

(1)添加元素

  • boolean add(E e): 确保此集合包含指定的元素(可选操作)。
  • boolean addAll(Collection<? extends E> c): 将指定集合中的所有元素添加到此集合中(可选操作)。

(2)删除元素

  • boolean remove(Object o): 从此集合中移除指定元素的单个实例,如果存在(可选操作)。
  • boolean removeAll(Collection<?> c): 移除此集合中所有也包含在指定集合中的元素(可选操作)。
  • default boolean removeIf(Predicate<? super E> filter): 移除满足给定条件的所有元素。
  • boolean retainAll(Collection<?> c): 仅保留此集合中包含在指定集合中的元素(可选操作)。
  • void clear(): 清除此集合中的所有元素(可选操作)。

(3)检查元素

  • boolean contains(Object o): 如果此集合包含指定的元素,则返回 true。
  • boolean containsAll(Collection<?> c): 如果此集合包含指定集合中的所有元素,则返回 true。
  • boolean isEmpty(): 如果此集合不包含元素,则返回 true。

(4)获取大小

  • int size(): 返回此集合中的元素数。

(5)转换为数组

  • Object[] toArray(): 返回包含此集合中所有元素的数组。
  • <T> T[] toArray(T[] a): 返回包含此集合中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。

(6)迭代器

  • Iterator<E> iterator(): 返回此集合中元素的迭代器。

(7)流操作

  • default Stream<E> stream(): 返回一个以此集合作为源的顺序流。
  • default Stream<E> parallelStream(): 返回可能并行的 Stream 与此集合作为其源。

(8)其他

  • boolean equals(Object o): 比较指定对象与此集合是否相等。
  • int hashCode(): 返回此集合的哈希码值。

(9)示例代码

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        // 创建一个ArrayList集合
        Collection<String> collection = new ArrayList<>();

        // 添加元素
        collection.add("Apple");
        collection.add("Banana");
        collection.add("Cherry");
        System.out.println("添加元素后: " + collection); // 输出: [Apple, Banana, Cherry]

        // 添加另一个集合的元素
        Collection<String> anotherCollection = new ArrayList<>();
        anotherCollection.add("Dragonfruit");
        anotherCollection.add("Elderberry");
        collection.addAll(anotherCollection);
        System.out.println("添加另一个集合后: " + collection); // 输出: [Apple, Banana, Cherry, Dragonfruit, Elderberry]

        // 删除元素
        collection.remove("Banana");
        System.out.println("删除'Banana'后: " + collection); // 输出: [Apple, Cherry, Dragonfruit, Elderberry]

        // 移除所有指定集合中的元素
        collection.removeAll(anotherCollection);
        System.out.println("移除所有另一个集合中的元素后: " + collection); // 输出: [Apple, Cherry]

        // 使用removeIf移除满足条件的元素
        collection.removeIf(s -> s.startsWith("A"));
        System.out.println("移除以'A'开头的元素后: " + collection); // 输出: [Cherry]

        // 仅保留指定集合中的元素
        collection.addAll(anotherCollection);
        collection.retainAll(anotherCollection);
        System.out.println("仅保留另一个集合中的元素后: " + collection); // 输出: [Dragonfruit, Elderberry]

        // 清空集合
        collection.clear();
        System.out.println("清空集合后: " + collection); // 输出: []

        // 重新添加元素以进行后续操作
        collection.add("Apple");
        collection.add("Banana");
        collection.add("Cherry");

        // 检查元素
        System.out.println("包含'Banana': " + collection.contains("Banana")); // 输出: true
        System.out.println("包含另一个集合的所有元素: " + collection.containsAll(anotherCollection)); // 输出: false

        // 检查集合是否为空
        System.out.println("集合是否为空: " + collection.isEmpty()); // 输出: false

        // 获取集合大小
        System.out.println("集合的大小: " + collection.size()); // 输出: 3

        // 转换为数组
        Object[] array = collection.toArray();
        System.out.println("从集合转换的数组: " + java.util.Arrays.toString(array)); // 输出: [Apple, Banana, Cherry]

        // 使用指定的数组类型转换
        String[] stringArray = collection.toArray(new String[0]);
        System.out.println("从集合转换的字符串数组: " + java.util.Arrays.toString(stringArray)); // 输出: [Apple, Banana, Cherry]

        // 迭代器
        System.out.print("遍历集合: ");
        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println(); // 输出: 遍历集合: Apple Banana Cherry

        // 流操作
        List<String> uppercaseList = collection.stream().map(String::toUpperCase).collect(Collectors.toList());
        System.out.println("从集合生成的全大写列表: " + uppercaseList); // 输出: [APPLE, BANANA, CHERRY]

        // 并行流操作
        List<String> uppercaseParallelList = collection.parallelStream().map(String::toUpperCase).collect(Collectors.toList());
        System.out.println("从集合生成的并行全大写列表: " + uppercaseParallelList); // 输出: [APPLE, BANANA, CHERRY]

        // 比较集合
        Collection<String> sameCollection = new ArrayList<>();
        sameCollection.add("Apple");
        sameCollection.add("Banana");
        sameCollection.add("Cherry");
        System.out.println("集合是否与sameCollection相等: " + collection.equals(sameCollection)); // 输出: true

        // 获取哈希码
        System.out.println("集合的哈希码: " + collection.hashCode()); // 输出: 哈希码值,具体值取决于元素和顺序
    }
}

3. ArrayList

ArrayList 是 Java 中的一个非常重要的集合框架类,它实现了 List 接口,并提供了可调整大小的数组实现。

(1)特点

  • 动态数组:与传统的数组不同,ArrayList 在运行时可以动态地调整其大小,这提供了极大的灵活性。
  • 易于使用:ArrayList 提供了丰富的接口和方法,使得添加、删除、访问和修改列表中的元素变得非常容易。
  • 接口丰富:实现了 List 接口,意味着它拥有 List 的所有功能,并且可以很容易地与 Java 集合框架的其他部分交互。
  • 性能:对于随机访问元素来说,ArrayList 的效率很高,因为它底层是数组。

(2)常用方法

① 构造方法
  • ArrayList(): 创建一个空的 ArrayList。
  • ArrayList(Collection<? extends E> c): 创建一个包含指定集合元素的 ArrayList。
  • ArrayList(int initialCapacity): 创建一个具有指定初始容量的空 ArrayList。
② 元素添加
  • boolean add(E e): 在列表末尾添加元素。
  • void add(int index, E element): 在指定位置添加元素。
  • boolean addAll(Collection<? extends E> c): 添加指定集合中的所有元素到列表末尾。
  • boolean addAll(int index, Collection<? extends E> c): 将指定集合中的所有元素插入到列表中的指定位置。
③ 元素删除
  • void clear(): 移除列表中的所有元素。
  • boolean remove(Object o): 移除列表中首次出现的指定元素。
  • E remove(int index): 移除列表中指定位置的元素。
  • boolean removeAll(Collection<?> c): 移除列表中包含在指定集合中的所有元素。
  • boolean removeIf(Predicate<? super E> filter): 移除满足给定条件的所有元素。
  • protected void removeRange(int fromIndex, int toIndex): 私有方法,用于移除列表中指定范围的元素。
  • boolean retainAll(Collection<?> c): 仅保留列表中包含在指定集合中的元素。
④ 元素修改
  • E set(int index, E element): 用指定元素替换列表中指定位置的元素。
⑤ 元素查询
  • boolean contains(Object o): 如果列表包含指定的元素,则返回 true。
  • boolean containsAll(Collection<?> c): 如果列表包含指定集合的所有元素,则返回 true。
  • E get(int index): 返回列表中指定位置的元素。
  • int indexOf(Object o): 返回列表中首次出现的指定元素的索引,如果不存在则返回 -1。
  • int lastIndexOf(Object o): 返回列表中最后一次出现的指定元素的索引,如果不存在则返回 -1。
  • boolean isEmpty(): 如果列表不包含元素,则返回 true。
⑥ 转换操作
  • Object[] toArray(): 返回一个包含列表所有元素的数组。
  • <T> T[] toArray(T[] a): 返回一个包含列表所有元素的数组;返回数组的运行时类型是指定数组的类型。
⑦ 视图和迭代器
  • List<E> subList(int fromIndex, int toIndex): 返回列表中指定的 fromIndex(包含)和 toIndex(不包含)之间的部分视图。
  • Iterator<E> iterator(): 返回列表中的迭代器。
  • ListIterator<E> listIterator(): 返回列表中的列表迭代器。
  • ListIterator<E> listIterator(int index): 返回列表中从指定位置开始的列表迭代器。
⑧ 大小和容量
  • int size(): 返回列表中的元素数量。
  • void ensureCapacity(int minCapacity): 如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数指定的元素数量。
⑨ 其他
  • void trimToSize(): 修改这个 ArrayList 实例的容量为列表的当前大小。
  • protected void finalize(): 当垃圾回收器确定不再有对对象的引用时,由垃圾回收器调用此方法。

(3)示例代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class Main {
    public static void main(String[] args) {
        // 创建一个空的 ArrayList
        ArrayList<String> list = new ArrayList<>();

        // 添加元素
        list.add("Apple"); // list: [Apple]
        list.add("Banana"); // list: [Apple, Banana]
        list.add(1, "Cherry"); // list: [Apple, Cherry, Banana]

        // 添加集合中的所有元素
        ArrayList<String> fruitsToBeAdded = new ArrayList<>(Arrays.asList("Date", "Elderberry"));
        list.addAll(fruitsToBeAdded); // list: [Apple, Cherry, Banana, Date, Elderberry]

        // 输出列表
        System.out.println(list); // 实际输出: [Apple, Cherry, Banana, Date, Elderberry]

        // 移除元素
        list.remove("Banana"); // list: [Apple, Cherry, Date, Elderberry]
        list.remove(2); // list: [Apple, Cherry, Elderberry]

        // 移除满足条件的所有元素
        list.removeIf(s -> s.startsWith("E")); // list: [Apple, Cherry]

        // 替换元素
        list.set(1, "Grape"); // list: [Apple, Grape]

        // 查询元素
        boolean containsApple = list.contains("Apple"); // containsApple: true
        System.out.println(containsApple); // 实际输出: true

        // 获取元素
        String firstElement = list.get(0); // firstElement: Apple
        System.out.println(firstElement); // 实际输出: Apple

        // 查找元素的索引
        int indexOfGrape = list.indexOf("Grape"); // indexOfGrape: 1
        System.out.println(indexOfGrape); // 实际输出: 1

        // 检查列表是否为空
        boolean isEmpty = list.isEmpty(); // isEmpty: false
        System.out.println(isEmpty); // 实际输出: false

        // 转换操作
        Object[] array = list.toArray(); // array: [Apple, Grape]
        System.out.println(Arrays.toString(array)); // 实际输出: [Apple, Grape]

        // 视图和迭代器
        List<String> sublist = list.subList(0, 1); // sublist: [Apple]
        System.out.println(sublist); // 实际输出: [Apple]

        // 迭代器
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next()); // 实际输出: Apple Grape
        }

        // 列表迭代器
        ListIterator<String> listIterator = list.listIterator();
        while (listIterator.hasNext()) {
            System.out.println(listIterator.nextIndex() + ": " + listIterator.next()); // 实际输出: 0: Apple 1: Grape
        }

        // 大小和容量
        int size = list.size(); // size: 2
        System.out.println(size); // 实际输出: 2

        // 确保容量
        list.ensureCapacity(10); // 确保列表至少可以容纳10个元素

        // 修改容量为当前大小
        list.trimToSize(); // 修改列表的容量为当前元素数量

        // 清除所有元素
        list.clear(); // list: []
        System.out.println(list); // 实际输出: []
    }
}

4. HashSet

HashSet 是 Java 集合框架中的一部分,它实现了 Set 接口,背后是由 HashMap 支持的。以下是 HashSet 的一些特点和它提供的主要函数。

(1)特点

  • 不包含重复元素:HashSet 中不允许有重复的元素,如果试图添加一个已经在 HashSet 中的元素,则添加操作不会产生任何效果。
  • 不保证元素的顺序:HashSet 不保证元素的顺序,也就是说,它不会按照元素的添加顺序保存元素。
  • 非线程安全:HashSet 不是线程同步的,如果多个线程同时访问 HashSet,并且至少有一个线程修改了 HashSet,则必须保持外部同步。
  • 允许包含 null 值:HashSet 可以包含一个 null 元素。
  • 高性能:HashSet 提供了常数时间性能的添加、删除和包含操作,前提是哈希函数能够将元素正确地分散到各个桶中。

(2)常用方法

① 构造函数
  • HashSet(): 创建一个默认初始容量为16,加载因子为0.75的空集合。
  • HashSet(int initialCapacity): 创建一个指定初始容量的空集合。
  • HashSet(int initialCapacity, float loadFactor): 创建一个指定初始容量和加载因子的空集合。
  • HashSet(Collection<? extends E> c): 创建一个包含指定集合中的元素的集合。
② 增加元素
  • boolean add(E e): 如果集合中没有指定元素,则添加并返回true,否则返回false。
  • boolean addAll(Collection<? extends E> c): 将指定集合中的所有元素添加到此集合中,如果集合因此改变,则返回true。
③ 删除元素
  • boolean remove(Object o): 如果存在,则从集合中移除指定元素,并返回true。
  • boolean removeAll(Collection<?> c): 移除此集合中那些也包含在指定集合中的所有元素,如果此集合因此改变,则返回true。
  • boolean retainAll(Collection<?> c): 仅保留此集合中那些也包含在指定集合中的元素,如果此集合因此改变,则返回true。
  • void clear(): 从此集合中移除所有元素。
④ 查找元素
  • boolean contains(Object o): 如果此集合包含指定的元素,则返回true。
  • boolean containsAll(Collection<?> c): 如果此集合包含指定集合中的所有元素,则返回true。
  • boolean isEmpty(): 如果此集合不包含任何元素,则返回true。
  • int size(): 返回此集合中的元素数量。
⑤ 其他方法
  • boolean removeIf(Predicate<? super E> filter): 移除此集合中满足给定谓词的所有元素。
  • void forEach(Consumer<? super E> action): 对此集合中的每个元素执行给定操作。
  • Spliterator<E> spliterator(): 在此集合中的元素上创建一个Spliterator。
  • Stream<E> stream(): 返回此集合中元素的串行流。
  • Stream<E> parallelStream(): 返回此集合中元素的并行流。
  • Object clone(): 返回此 HashSet 实例的浅拷贝。
  • int hashCode(): 返回此集合的哈希码值。
  • boolean equals(Object o): 比较指定对象与此集合是否相等。

(3)示例代码

import java.util.Collection;
import java.util.HashSet;
import java.util.Spliterator;
import java.util.stream.Stream;

public class Main {

    public static void main(String[] args) {
        // 创建一个默认初始容量为16,加载因子为0.75的空集合
        HashSet<String> hashSet = new HashSet<>();

        // 添加元素
        System.out.println(hashSet.add("Apple")); // true
        System.out.println(hashSet.add("Banana")); // true
        System.out.println(hashSet.add("Apple")); // false,因为已经存在

        // 使用指定初始容量的空集合
        HashSet<String> hashSetWithCapacity = new HashSet<>(30);

        // 使用指定初始容量和加载因子的空集合
        HashSet<String> hashSetWithLoadFactor = new HashSet<>(30, 0.5f);

        // 创建一个包含指定集合中的元素的集合
        Collection<String> collection = new HashSet<>();
        collection.add("Cherry");
        collection.add("Date");
        HashSet<String> hashSetFromCollection = new HashSet<>(collection);
        System.out.println(hashSetFromCollection); // [Cherry, Date]

        // 将指定集合中的所有元素添加到此集合中
        System.out.println(hashSet.addAll(hashSetFromCollection)); // true

        // 从集合中移除指定元素
        System.out.println(hashSet.remove("Banana")); // true

        // 移除此集合中那些也包含在指定集合中的所有元素
        System.out.println(hashSet.removeAll(collection)); // true

        // 仅保留此集合中那些也包含在指定集合中的元素
        hashSet.add("Apple");
        hashSet.add("Banana");
        System.out.println(hashSet.retainAll(hashSetFromCollection)); // true

        // 从此集合中移除所有元素
        hashSet.clear();
        System.out.println(hashSet.isEmpty()); // true

        // 查找元素
        hashSet.add("Apple");
        System.out.println(hashSet.contains("Apple")); // true
        System.out.println(hashSet.containsAll(collection)); // false

        // 返回此集合中的元素数量
        System.out.println(hashSet.size()); // 1

        // Java 8 新增方法
        // 移除此集合中满足给定谓词的所有元素
        hashSet.add("Banana");
        hashSet.removeIf(s -> s.startsWith("B"));
        System.out.println(hashSet); // [Apple]

        // 对此集合中的每个元素执行给定操作
        hashSet.forEach(s -> System.out.println(s)); // Apple

        // 在此集合中的元素上创建一个Spliterator
        Spliterator<String> spliterator = hashSet.spliterator();
        spliterator.forEachRemaining(System.out::println); // Apple

        // 返回此集合中元素的串行流
        Stream<String> stream = hashSet.stream();
        stream.forEach(System.out::println); // Apple

        // 返回此集合中元素的并行流
        Stream<String> parallelStream = hashSet.parallelStream();
        parallelStream.forEach(System.out::println); // Apple

        // 返回此 HashSet 实例的浅拷贝
        HashSet<String> cloneHashSet = (HashSet<String>) hashSet.clone();
        System.out.println(cloneHashSet); // [Apple]

        // 返回此集合的哈希码值
        System.out.println(hashSet.hashCode()); 

        // 比较指定对象与此集合是否相等
        System.out.println(hashSet.equals(cloneHashSet)); // true
    }
}

二、Map接口

1. 常用的Map衍生类

(1)HashMap类 

它基于哈希表实现,存储键值对,允许使用null键和null值。它不保证元素的顺序,特别适合在插入和查询操作中快速访问元素。

(2)LinkedHashMap类 

继承自HashMap,但它维护了一个运行于所有条目的双重链接列表。这个链接列表定义了迭代顺序,通常是插入顺序,也可以在构造时指定为访问顺序。

(3)TreeMap类 

基于红黑树实现,可以确保键值对按照键的自然顺序或者Comparator排序。它提供了操作键值对的各种方法,如获取第一个键、最后一个键等。

(4)Hashtable类 

它是遗留类,与HashMap类似,但它不允许使用null键或null值,并且所有的方法都是同步的,即线程安全的。

(5)ConcurrentHashMap类 

是一个线程安全的哈希表,用于替代Hashtable。它支持高并发性,通过分段锁技术,允许多个线程并发访问Map的不同部分。

2. HashMap

(1)特点

  • 键值对存储:HashMap基于键值对(Key-Value Pair)存储数据,每个键对应一个值,通过键可以快速找到对应的值。
  • 快速访问:HashMap通过哈希表实现,它提供了常数时间复杂度(O(1))的查找、插入和删除操作,使得数据访问非常高效。
  • 允许一个键为null:HashMap允许使用一个null键和多个null值。null键只能有一个,因为键的唯一性要求。
  • 非线程安全:HashMap不是线程安全的,如果多个线程同时访问HashMap,并且至少有一个线程修改了映射,则必须保持外部同步。
  • 初始容量和负载因子:HashMap有两个重要的参数,初始容量和负载因子。初始容量是哈希表创建时的容量,负载因子是哈希表在其容量自动增加之前可以达到多满的一种度量。这两个参数可以影响HashMap的性能。

(2)常用方法

① 构造函数
  • HashMap(): 创建一个默认初始容量为16(必须是2的幂)和默认加载因子为0.75的空HashMap。
  • HashMap(int initialCapacity): 创建一个指定初始容量的HashMap,加载因子为0.75。
  • HashMap(int initialCapacity, float loadFactor): 创建一个指定初始容量和加载因子的HashMap。
  • HashMap(Map<? extends K, ? extends V> m): 创建一个包含指定映射的HashMap。
② 增删改查和遍历
  • put(K key, V value): 添加键值对到HashMap中。
  • remove(Object key): 删除指定键的键值对。
  • replace(K key, V value): 替换指定键的值。
  • get(Object key): 获取指定键的值。
  • containsKey(Object key): 检查HashMap是否包含指定的键。
  • containsValue(Object value): 检查HashMap是否包含指定的值。
  • forEach(BiConsumer<? super K, ? super V> action): 对HashMap中的每个键值对执行给定的操作。
③ 获取key和value
  • keySet(): 返回HashMap中所有键的视图集。
  • values(): 返回HashMap中所有值的视图集。
  • entrySet(): 返回HashMap中所有键值对的视图集。
④ Stream流
  • keySet().stream(): 返回HashMap中键的Stream流。
  • entrySet().stream(): 返回HashMap中键值对的Stream流。
⑤ 其他方法
  • size(): 返回HashMap中的键值对数量。
  • isEmpty(): 检查HashMap是否为空。
  • clear(): 清空HashMap中的所有键值对。
  • putAll(Map<? extends K, ? extends V> m): 将指定映射的所有键值对添加到HashMap中。
  • clone(): 返回HashMap的一个浅拷贝。
  • replaceAll(BiFunction<? super K, ? super V, ? extends V> function): 将HashMap中的每个键值对替换为给定函数的结果。
  • compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction): 尝试计算指定键的值。
  • computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction): 如果指定键不存在,则尝试计算其值并插入。
  • computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction): 如果指定键存在,则尝试计算其值并替换。

(3)示例代码

import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        // 构造函数示例
        HashMap<String, Integer> fruitPrices = new HashMap<>();
        HashMap<String, Integer> fruitPricesWithCapacity = new HashMap<>(32);
        HashMap<String, Integer> fruitPricesWithCapacityAndLoadFactor = new HashMap<>(32, 0.8f);
        HashMap<String, Integer> fruitPricesWithMap = new HashMap<>(Map.of("Apple", 2, "Banana", 5));

        // 增删改查和遍历示例
        fruitPrices.put("Apple", 2);
        fruitPrices.put("Banana", 5);
        fruitPrices.put("Cherry", 10);
        fruitPrices.remove("Banana");
        fruitPrices.replace("Apple", 10);
        Integer applePrice = fruitPrices.get("Apple");
        boolean hasApple = fruitPrices.containsKey("Apple");
        boolean hasPrice = fruitPrices.containsValue(10);
        fruitPrices.forEach((fruit, price) -> System.out.println(fruit + "的价格是:" + price));

        // 获取key和value示例
        System.out.println("所有的水果:" + fruitPrices.keySet());
        System.out.println("所有水果的价格:" + fruitPrices.values());

        // Stream流示例
        System.out.println("所有水果名称的Stream流:" + fruitPrices.keySet().stream().collect(Collectors.toList()));
        System.out.println("所有水果键值对的Stream流:" + fruitPrices.entrySet().stream().collect(Collectors.toList()));

        // 其他方法示例
        int size = fruitPrices.size();
        boolean isEmpty = fruitPrices.isEmpty();
        fruitPrices.clear();
        fruitPrices.putAll(Map.of("Apple", 2, "Banana", 5));
        HashMap<String, Integer> clonedFruitPrices = (HashMap<String, Integer>) fruitPrices.clone();
        fruitPrices.replaceAll((fruit, price) -> price + 1); // 每个价格加1
        fruitPrices.compute("Apple", (fruit, price) -> price - 1); // Apple的价格减1
        fruitPrices.computeIfAbsent("Cherry", fruit -> 10);
        fruitPrices.computeIfPresent("Banana", (fruit, price) -> price + 2); // Banana的价格加2

        // 遍历方法示例
        System.out.println("使用for循环遍历:");
        for (Map.Entry<String, Integer> entry : fruitPrices.entrySet()) {
            System.out.println(entry.getKey() + "的价格是:" + entry.getValue());
        }

        System.out.println("使用增强for循环遍历:");
        for (String fruit : fruitPrices.keySet()) {
            System.out.println(fruit + "的价格是:" + fruitPrices.get(fruit));
        }

        // 根据key查询和修改value示例
        System.out.println("修改前Apple的价格:" + fruitPrices.get("Apple"));
        fruitPrices.put("Apple", 5);
        System.out.println("修改后Apple的价格:" + fruitPrices.get("Apple"));
    }
}

三、集合练习

1. ArrayList

(1)定义一个ArrayList,并添加以下元素:1, 2, 3, 4, 5。然后使用循环遍历并打印所有元素。

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> arr = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            arr.add(i);
        }

        for(Integer a :arr){
            System.out.print(a+" ");//1 2 3 4 5 
        }
        System.out.println();

        arr.forEach(s-> System.out.print(s+" "));//1 2 3 4 5 
        System.out.println();

        //System.out.println(arr);
    }
}

(2)移除索引为2的元素,并输出修改后的ArrayList。

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> fruitList = new ArrayList<>();
        fruitList.add("apple");
        fruitList.add("banana");
        fruitList.add("cherry");
        fruitList.add("date");
        fruitList.add("fig");

        fruitList.remove("cherry");
        //fruitList.remove(2); //或移除2号索引

        System.out.println(fruitList); //[apple, banana, date, fig]
    }
}

(3)给定一个包含整数的ArrayList,编写一个方法来计算所有元素的和。

import java.util.ArrayList;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {

        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i <= 100; i++) {
            list.add(i);
        }

        // 方法一:
        Integer sum1 = 0;
        for (Integer i : list) {
            sum1 += i;
        }
        System.out.println(sum1); // 5050

        // 方法二:
        int sum2 = list.stream().mapToInt(Integer::intValue).sum();
        System.out.println(sum2); // 5050

    }
}

(4)给定一个包含字符串的ArrayList,编写一个方法来删除所有包含字母“b”的字符串。

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>(
                List.of("apple", "banana", "watermelon", "peach", "strawberry")
        );
        list.removeIf(s -> s.contains("b"));
        System.out.println(list);// [apple, watermelon, peach]

    }
}

(5)将ArrayList反转,并输出反转后的ArrayList。(使用Collections)

import java.util.ArrayList;
import java.util.Collections;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> fruitList = new ArrayList<>();
        fruitList.add("apple");
        fruitList.add("banana");
        fruitList.add("cherry");
        fruitList.add("date");
        fruitList.add("fig");

        Collections.reverse(fruitList);
        System.out.println(fruitList); //[fig, date, cherry, banana, apple]
    }
}

(6)给定一个包含整数的ArrayList,编写一个方法来找出最大的元素。

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>(
                List.of(1, 3, 5, 7, 9, 10)
        );

        //方法一
        Integer MAX1 = Integer.MIN_VALUE;
        for (Integer i : list) {
            if (MAX1 < i) {
                MAX1 = i;
            }
        }
        System.out.println(MAX1); // 10

        //方法二
        Optional<Integer> MAX2 = list.stream().max(Integer::compareTo);
        MAX2.ifPresent(System.out::println); // 10

        //方法三
        OptionalInt MAX3 = list.stream().mapToInt(Integer::intValue).max();
        MAX3.ifPresent(System.out::println); // 10

    }
}

(7)给定两个包含整数的ArrayList,编写一个方法来合并这两个ArrayList,并去除重复元素,并进行排序。

import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<>(
                List.of(1, 3, 5, 7, 9, 10)
        );
        ArrayList<Integer> list2 = new ArrayList<>(
                List.of(1, 2, 3, 4, 5, 6)
        );
        // 方法一
        TreeSet<Integer> set = new TreeSet<>();
        set.addAll(list1);
        set.addAll(list2);
        ArrayList<Integer> arr1 = new ArrayList<>(set);
        System.out.println(arr1); // [1, 2, 3, 4, 5, 6, 7, 9, 10]

        // 方法二
        List<Integer> collect = Stream.concat(list1.stream(), list2.stream())
                .distinct()
                .sorted()
                .collect(Collectors.toList());
        ArrayList<Integer> arr2 = (ArrayList<Integer>) collect; // 向下转型 List<> -> ArrayList<>
        System.out.println(arr2); // [1, 2, 3, 4, 5, 6, 7, 9, 10]

    }
}

(8)给定一个整型ArrayList {10, 20, 30, 40, 50},请找出数字30的索引位置,并输出结果。

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>(
                List.of(10, 20, 30, 40, 50)
        );

        System.out.println(list.indexOf(30)); //2

    }
}

(9)给定一个整型ArrayList {1, 2, 3, 4, 5},将其每个元素乘以2,并输出结果。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>(
                Arrays.asList(1, 2, 3, 4, 5)
        );

        // 方法一
        for (int i = 0; i < numbers.size(); i++) {
            numbers.set(i, numbers.get(i) * 2);
        }
        System.out.println(numbers);

        // 方法二
        List<Integer> collect = numbers.stream().map(s -> s * 2).collect(Collectors.toList());
        System.out.println(collect);

    }
}

(10)Collections练习

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        // 练习题1:创建一个包含5个整数的ArrayList,并输出
        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);
        list1.add(4);
        list1.add(5);
        System.out.println("练习题1:输出ArrayList:" + list1); // 练习题1的输出:[1, 2, 3, 4, 5]

        // 练习题2:使用Collections.sort()对ArrayList进行排序
        Collections.sort(list1);
        System.out.println("练习题2:升序排序后的ArrayList:" + list1); // 练习题2的输出:[1, 2, 3, 4, 5]
        Collections.sort(list1, Collections.reverseOrder());
        System.out.println("练习题2:降序排序后的ArrayList:" + list1); // 练习题2的输出:[5, 4, 3, 2, 1]

        // 练习题3:使用Collections.reverse()对ArrayList进行反转
        Collections.reverse(list1);
        System.out.println("练习题3:反转后的ArrayList:" + list1); // 练习题3的输出:[1, 2, 3, 4, 5]

        // 练习题4:使用Collections.shuffle()对ArrayList进行随机排序
        Collections.shuffle(list1);
        System.out.println("练习题4:随机排序后的ArrayList:" + list1); // 练习题4的输出:[随机顺序的元素]

        // 练习题5:使用Collections.min()找出ArrayList中的最小值
        System.out.println("练习题5:ArrayList中的最小值:" + Collections.min(list1)); // 练习题5的输出:1

        // 练习题6:使用Collections.max()找出ArrayList中的最大值
        System.out.println("练习题6:ArrayList中的最大值:" + Collections.max(list1)); // 练习题6的输出:5

        // 练习题7:使用Collections.fill()将ArrayList中的所有元素替换为一个指定的值
        Collections.fill(list1, 10);
        System.out.println("练习题7:替换后的ArrayList:" + list1); // 练习题7的输出:[10, 10, 10, 10, 10]

        // 练习题8:使用Collections.binarySearch()在已排序的ArrayList中查找一个元素
        Collections.sort(list1);
        System.out.println("练习题8:元素10在ArrayList中的位置:" + Collections.binarySearch(list1, 10)); // 练习题8的输出:2

        // 练习题9:使用Collections.indexOfSubList()查找子列表在ArrayList中的位置
        List<Integer> sublist = new ArrayList<>();
        sublist.add(10);
        sublist.add(10);
        System.out.println("练习题9:子列表在ArrayList中的位置:" + Collections.indexOfSubList(list1, sublist)); // 练习题9的输出:-1(因为子列表长度不匹配)

        // 练习题10:使用Collections.lastIndexOfSubList()查找子列表在ArrayList中最后一次出现的位置
        System.out.println("练习题10:子列表在ArrayList中最后一次出现的位置:" + Collections.lastIndexOfSubList(list1, sublist)); // 练习题10的输出:3

        // 练习题11:使用Collections.replaceAll()将ArrayList中的某个元素替换为另一个元素
        Collections.replaceAll(list1, 10, 20);
        System.out.println("练习题11:替换后的ArrayList:" + list1); // 练习题11的输出:[20, 20, 20, 20, 20]

        // 练习题12:使用Collections.frequency()统计ArrayList中某个元素出现的次数
        System.out.println("练习题12:元素20在ArrayList中出现的次数:" + Collections.frequency(list1, 20)); // 练习题12的输出:5

        // 练习题13:使用Collections.emptyList()创建一个空的ArrayList
        List<Integer> emptyList = Collections.emptyList();
        System.out.println("练习题13:空的ArrayList:" + emptyList); // 练习题13的输出:[]

        // 练习题14:使用Collections.singletonList()创建一个只包含一个元素的ArrayList
        List<Integer> singleList = Collections.singletonList(30);
        System.out.println("练习题14:只包含一个元素的ArrayList:" + singleList); // 练习题14的输出:[30]

        // 练习题15:使用Collections.synchronizedList()创建一个线程安全的ArrayList
        List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());
        synchronizedList.add(40);
        System.out.println("练习题15:线程安全的ArrayList:" + synchronizedList); // 练习题15的输出:[40]
    }
}

2. HashSet

(11)判断HashSet中是否包含某个元素。

import java.util.HashSet;

public class Main {
    public static void main(String[] args) {
        HashSet<String> hashSet = new HashSet<>();
        hashSet.add("Apple");
        hashSet.add("Banana");
        hashSet.add("Cherry");

        boolean contains = hashSet.contains("Banana");
        System.out.println(contains); //true
    }
}

(12)从HashSet中删除一个元素,并输出删除后的HashSet。

import java.util.HashSet;

public class Main {
    public static void main(String[] args) {
        HashSet<String> hashSet = new HashSet<>();
        hashSet.add("Apple");
        hashSet.add("Banana");
        hashSet.add("Cherry");

        hashSet.remove("Banana");
        System.out.println(hashSet);
    }
}

(13)遍历HashSet中的所有元素。

import java.util.HashSet;
import java.util.Iterator;

public class Main {
    public static void main(String[] args) {
        HashSet<String> hashSet = new HashSet<>();
        hashSet.add("Apple");
        hashSet.add("Banana");
        hashSet.add("Cherry");

        Iterator<String> iterator = hashSet.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();

        for (String i : hashSet) {
            System.out.print(i + " ");
        }
        System.out.println();
        
        hashSet.forEach(s -> System.out.print(s + " "));
        System.out.println();

    }
}

(14)创建一个HashSet,移除所有偶数。

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        HashSet<Integer> hashSet = new HashSet<>(
                Set.of(1, 2, 3, 4, 5, 2)
        );

        // 方法一
        hashSet.removeIf(e -> e % 2 == 0);
        System.out.println(hashSet);

        // 方法二
        Iterator<Integer> iterator = hashSet.iterator();
        while (iterator.hasNext()) {
            Integer e = iterator.next();
            if (e % 2 == 0) {
                // 不能写 hashSet.remove(e);
                // 不能在迭代器迭代过程中直接修改集合(例如使用remove方法)
                // 否则会抛出ConcurrentModificationException异常。
                // 这是因为迭代器依赖于集合的内部状态,
                // 而直接修改集合会破坏这种状态。
                iterator.remove();
            }
        }
        System.out.println(hashSet);


    }
}

(15)给定两个HashSet,创建一个方法来计算它们的并集。

import java.util.HashSet;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        HashSet<Integer> set1 = new HashSet<>(Set.of(1, 2, 3));
        HashSet<Integer> set2 = new HashSet<>(Set.of(3, 4, 5));

        HashSet<Integer> Union = new HashSet<>(set1);
        Union.addAll(set2);
        System.out.println(Union);

        HashSet<Integer> collect = Stream.concat(set1.stream(), set2.stream())
                .collect(Collectors.toCollection(HashSet::new));
        System.out.println(collect);

    }
}

(16)给定一个整数数组,去除重复元素,并按降序排列。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Integer[] arr = {1, 2, 2, 2, 3, 3, 4, 5, 6};
        TreeSet<Integer> integers = new TreeSet<>(Collections.reverseOrder());
        integers.addAll(Arrays.asList(arr));
        System.out.println(integers);

    }
}

3. HashMap

(17)创建一个HashMap,并添加5个键值对,然后遍历并打印所有键值对。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Apple", 1);
        map.put("Banana", 2);
        map.put("Cherry", 3);
        map.put("Date", 4);
        map.put("Elderberry", 5);

        // 方式一
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        for (Map.Entry<String, Integer> en : entries) {
            System.out.println(en.getKey() + ":" + en.getValue());
        }
        System.out.println();

        // 方式二
        Set<String> keys = map.keySet();
        for (var key : keys) {
            System.out.println(key + ":" + map.get(key));
        }
        System.out.println();

        // 方式三
        map.forEach((key, value) -> System.out.println(key + ":" + value));
        

    }
}

(18)检查HashMap中是否包含某个键或值?

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Apple", 1);
        map.put("Banana", 2);
        map.put("Cherry", 3);

        // 检查键
        if (map.containsKey("Apple")) {
            System.out.println("Key 'Apple' exists.");
        } else {
            System.out.println("Key 'Apple' does not exist.");
        }

        // 检查值
        if (map.containsValue(3)) {
            System.out.println("Value 3 exists.");
        } else {
            System.out.println("Value 3 does not exist.");
        }
    }
}

(19)从HashMap中删除所有值为null的键值对。

import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("a", "apple");
        map.put("b", null);
        map.put("c", "cherry");

        map.values().removeIf(value -> value == null);

        System.out.println(map);
    }
}

(20)给定一个整数数组,找出数组中每个元素对应出现次数。

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 2, 1, 3, 4, 5, 4, 6};
        Map<Integer, Integer> countMap1 = new HashMap<>();

        // 方法一
        for (int number : numbers) {
            //getOrDefault(a,b)如果key含有a那么就取出a的值,否则就取出b
            countMap1.put(number, countMap1.getOrDefault(number, 0) + 1);
        }
        System.out.println(countMap1); //{1=2, 2=2, 3=2, 4=2, 5=1, 6=1}

        // 方法二
        Map<Integer, Long> countMap2 = IntStream.of(numbers)
                .boxed() // 将int转换为Integer
                .collect(Collectors.groupingBy(
                        e -> e, // 分组的键
                        Collectors.counting() // 计算每个键的出现次数
                ));
        System.out.println(countMap2); // 输出:{1=2, 2=2, 3=2, 4=2, 5=1, 6=1}


    }
}

(21)合并两个HashMap,如果键相同,则将对应的值相加。

import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> map1 = Map.of("a", 1, "b", 2);
        Map<String, Integer> map2 = Map.of("a", 3, "c", 4);

        Map<String, Integer> result = new HashMap<>(map1);
        map2.forEach((key, value) -> result.merge(key, value, Integer::sum));

        System.out.println(result); // 输出:{a=4, b=2, c=4}
    }
}

(22)反转HashMap中的键和值。

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> originalMap = new HashMap<>();
        originalMap.put("one", 1);
        originalMap.put("two", 2);
        originalMap.put("three", 3);

        Map<Integer, String> collect = originalMap.entrySet().stream()
                .collect(Collectors.toMap(e -> e.getValue(), e -> e.getKey()));

        System.out.println(collect);
    }
}

(23)将一个整数数组中的元素按照其出现的次数降序排序。

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static List<Integer> sortByFrequency(int[] nums) {
        Map<Integer, Long> frequencyMap = Arrays.stream(nums)
                .boxed()
                .collect(Collectors.groupingBy(e -> e, Collectors.counting()));

        return Arrays.stream(nums)
                .boxed()
                .sorted((a, b) -> frequencyMap.get(b).intValue() - frequencyMap.get(a).intValue())
                .collect(Collectors.toList());
    }

    public static void main(String[] args) {
        int[] nums = {1, 1, 1, 2, 2, 2, 3, 3, 4};
        System.out.println(sortByFrequency(nums)); // 输出:[1, 1, 1, 2, 2, 2, 3, 3, 4]
    }
}

(24)找出两个HashMap中共有的键(键的交集)。

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> map1 = new HashMap<>(
                Map.of("a", 1, "b", 2, "c", 3)
        );

        Map<String, Integer> map2 = new HashMap<>(
                Map.of("b", 2, "c", 3, "d", 4)
        );

        List<String> collect = map2.keySet().stream()
                .filter(s -> map1.containsKey(s))
                .collect(Collectors.toList());
        System.out.println(collect);

    }
}


(25)输出一个Map中最小和最大的Key。

import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        TreeMap<Integer, String> treeMap = new TreeMap<>();
        treeMap.put(1, "One");
        treeMap.put(3, "Three");
        treeMap.put(2, "Two");

        System.out.println("First Key: " + treeMap.firstKey());
        System.out.println("Last Key: " + treeMap.lastKey());
    }
}
// 输出:
// First Key: 1
// Last Key: 3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值